使用后台工作人员更新 datagridviews 后 GUI 冻结
我制作了一个同时运行三个后台工作者的应用程序。它基本上更新了三个数据网格视图,这是它正在做的事情。我的问题是,如果我按最大化框按钮或任何数据网格视图中的任何位置,程序都会挂起相当长的时间。我可以使用水平滚动,但不能使用垂直滚动。我尝试过Backgroundworker_runworkercompleted,它在线程更新各自的datagridviews后根据需要触发。这是正常行为还是我做错了什么任何建议都会有帮助。 PS:我已经使用步骤方法运行了整个程序,并且代码中没有无限循环。 提前致谢 约翰
I have made an application which runs three backgroundworkers simultaneously. It basically updates three datagridviews, which it is doing spot on. My problem is if I press maximizebox button or anywhere in any of the datagridview the program hangs for quite a long time. I am able to use the horizontal scroll but not vertical scrolls. I have tried Backgroundworker_runworkercompleted and it fires as required after threads have updated their respective datagridviews. Is it a normal behaviour or am i doing something wrong any suggestions would be helpful.
P.S: I have run the whole program using step method and their is no infinite loop in the code.
Thanks in advance
Jhon
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
将此行代码放在调用
Backgroundworker1.RunWorkerAsync()
之前,以暂时禁用 datagridview 滚动条。现在,通过在
BackgroundWorker1_RunWorkerCompleted
事件中添加这行代码来重新启用 datagridview 的滚动条。这永远不会使您的应用程序无响应。
Place this line of code just before when you are calling
Backgroundworker1.RunWorkerAsync()
to temporarily disable your datagridview scroll bars.Now Re-enable scroll bars of your datagridview by adding this line of code in
BackgroundWorker1_RunWorkerCompleted
event.This will never make your application unresponding.
听起来你仍然以某种方式阻塞 UI 线程。发布一些代码片段可能会对您有所帮助。另外,您的进程的 CPU 利用率是多少?如果 cpu 使用率很高,则可能会导致 UI 线程处于饥饿状态。
It sounds like you are still blocking the UI thread somehow. It may be helpful for you to post some code snippets. Also, what is the CPU utilization of your process? If the cpu usage is high, you may be starving the UI thread somehow.
好吧,我已经找到了问题的解决方案,在按顺序消除发现的问题点的同时,我在 backgroundworker.dowork 事件之外调用了我的 datagridview ,瞧,解决了问题。
这个故事的寓意是“永远不要从后台工作线程内更新数据网格视图”,特别是当您不知道自己做错了什么时:)。我希望它能帮助将来的人。
Okay I have found the solution to my problem, while working out sequential elimination of the perceived trouble spots, I called my datagridview outside of the backgroundworker.dowork event and voila that solved the problem.
Moral of the story "NEVER UPDATE A DATA GRID VIEW FROM WITHIN THE BACKGROUNDWORKER THREAD" specially when you don't know what are you doing wrong :). I hope it will help someone in future.
您必须确保从 UI 线程更新 datagridviews。
You have to make sure that you are updating the datagridviews from the UI thread.
我也有同样的问题。当我的 dataGridViews 从 UI 线程更新时,它们工作得很好。当我尝试从 backgroundWorker 向它们添加一系列行时,它们变得没有响应。
为了纠正这个问题,我将行添加到了数据表中。当我启动backgroundWorker时,我将dataGridView的.datasource属性设置为空。当工作人员完成后,我再次将其设置回数据表。这会强制 dataGridView 进行自我更新,并切断工作线程中发生的内容与 UI 中显示的内容之间的同步连接,这似乎减轻了工作线程完成时的无响应情况。
使用示例:
I had the same problem. When my dataGridViews were being updated from the UI thread, they worked fine. When I tried to add a series of rows to them from the backgroundWorker, they became unresponsive.
To correct this, I added the rows to a dataTable instead. When I kick off the backgroundWorker, I set the .datasource property of the dataGridView to nothing. When the worker completes, I set it back to the dataTable again. This both forces the dataGridView to update itself, and severs the synchronous connection between what it happening in the worker thread, and what is being displayed in the UI, which seems to alleviate the unresponsiveness when the worker completes.
Sample usage:
现在回答@Jhon 已经太晚了,但它似乎可能对其他人有帮助。
就我而言,我使用的是 BindingSource,并且只有在必须出现滚动条的记录太多时,UI 才会冻结。
当您使用后台工作程序、任务或线程来完成工作时,您必须更新主 UI 线程上的 UI 控件。
为此,您可以调用相应线程中的方法。
一个简单的例子:
但我更喜欢这个解决方案:
InvokeIfRequired
It's too late to answer to @Jhon but it seems like it might help other people.
In my case, I was using a BindingSource and the UI only froze if there where so many records that scrollbars had to appear.
When you use a background worker, task or thread to do the work, you have to update your UI controls on the main UI thread.
To do that you can Invoke a method in the corresponding thread.
A simple example:
But i prefer this solution:
InvokeIfRequired