在不阻塞主线程的情况下执行长时间运行的UI更改

时间:2012-10-31 12:23:06

标签: c# .net winforms multithreading backgroundworker

无论如何都要运行大量的UI更新而不影响C#winforms应用程序中的主线程吗?

当用户点击某个特定事件时,我希望避免长时间的延迟(在我的情况下,这是一种非常接近形式的处理内存的调用)

我知道我可以使用BackgroundWorker在“do work”事件中执行冗长的操作,但问题是您无法更改此事件中的任何UI(它将导致跨线程异常) - 所以我不能把我的大量关闭形式的电话放在这里。

我无法将关闭表单调用放在“worker completed”事件中,因为这是在主线程上运行的,最终会锁定主线程导致糟糕的用户体验。

我已经考虑过只在应用程序会话空闲时才产生一个处理关闭的线程,但不确定这是否会有点混乱。

1 个答案:

答案 0 :(得分:1)

您应该使用ProgressChanged BackgroundWorker事件更新UI。要将WorkerReportsProgress实例的此功能集BackgroundWorker属性设置为true。然后,您可以通过从DoWork事件处理程序发送数据来多次更新UI:

backgroundWorker.ReportProgress(percentage, yourCustomData);

建议Make Thread-Safe Calls to Windows Forms Controls。原因如下:

  

对Windows窗体控件的访问本质上不是线程安全的。如果你   有两个或多个线程来操纵控件的状态,它是   可能迫使控件进入不一致状态。其他   线程相关的错误也是可能的,包括竞争条件   和死锁。确保访问您的控件非常重要   以线程安全的方式完成。

     

.NET Framework可帮助您检测何时访问   以非线程安全的方式控制。当你跑步   您在调试器中的应用程序,以及除此之外的其他线程   它创建了一个控件,试图调用该控件,即调试器   使用“控件控件”消息引发InvalidOperationException   从其创建的线程以外的线程访问的名称。“

     

此异常在调试期间可靠地发生,并且在某些情况下   情况,在运行时。强烈建议你解决这个问题   当你看到它时会出现问题。

您可以禁用该例外:

Form.CheckForIllegalCrossThreadCalls = false;

但控件可能(有时会)停止工作。