[英]Backgroundworker/Control.BeginInvoke() freezing UI
我有一些执行Windows svc(另一个过程)并同时更新UI的代码。 调用使用BeginInvoke
,如下所示:
Install.BeginInvoke((MethodInvoker) delegate { Install.Enabled = false; });
这在DoWork
事件处理程序中。 但是,UI仍然冻结。 我是否需要在某个地方调用Application.DoEvents
(如果需要,在哪里?)? 如何消除冻结?
在按钮中单击,我有:
GetPrinterDto(DirectoriesTreeView.SelectedNode.Text);
InstallBackgoundWorker.RunWorkerAsync();
InstallBackgroundWorker
只运行更新UI等的代码。
我正在尝试做的是调用WCF服务器(托管在Windows服务中-很好),但是当这样做时,请以异步方式用任意值更新进度条和标签。 当我选择一个treenode时,将为选定的treenode填充事件处理程序,这可能会导致某些速度下降。 我将尝试将其放在自己的背景工作人员中。
您当然可以在DoWork
方法中发出调用以更新UI(这是对BeginInvoke
的调用所做的事情),但您不应该这样做,否则,您实际上不需要BackgroundWorker
类。
相反,您将调用ReportProgress
方法 ,该方法将随后触发ProgressChanged
事件 。
您将在ProgressChanged
事件的事件处理程序中调用Install.Enabled = false
。
该问题与BeginInvoke
的使用没有直接关系。 它可能与被调用的数量有关。 您可以将ReportProgress
与ProgressChanged
事件结合使用,但是假设您用ReportProgress
替换了所有BeginInvoke
调用,那么您可能会遇到类似的问题,因为BackgroundWorker
将使用与BeginInvoke
/ Invoke
相同的机制自动在UI线程上封送事件处理程序。无论如何都在使用。 我想说的快速解决方案是减少您尝试更新UI的频率。
就个人而言,我觉得用BeginInvoke
更新与工作线程进步的UI是方式过度使用。 同样, BackgroundWorker
类也促进了这种次优方法。 通常最好让工作线程定期将更新信息发布到共享的数据结构中,然后UI线程可以按自己的计划(通常通过使用Timer
轮询)来获取它。 这有几个优点:
Control.Invoke\\Control.BeginInvoke
施加的UI和工作线程之间的紧密耦合。 不幸的是, BackgroundWorker
缺少使用这种替代方法的必要机制。 但是,你应该没使用ReportProgress
只要你不把它过于频繁。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.