MSDN文章:How to: Make Thread-Safe Calls to Windows Forms Controls 我们应该使用异步委托进行调用。但为什么异步代理会使呼叫安全?
答案 0 :(得分:1)
您将调用control.BeginInvoke()或control.Invoke()并且该方法将负责安全地在GUI分派线程中插入您的委托,因此稍后您的委托将在GUI中处理和执行线程而不是
中的线程答案 1 :(得分:1)
底线是:您不应该从创建控件的线程(UI /主线程)以外的线程更新UI控件。否则你可能会看到一些不可预测的行为。
如果需要从工作线程(主线程除外)更新UI,则需要在更新UI之前切换回UI线程。
文章建议使用
IsInvokeRequired
(如果当前线程不是创建UI的那个,则返回true。)和Invoke(delegate)
在正确的/ UI线程上运行委托。当您想要更新>>异步过程中的UI 时,此功能非常有用。例如在UI上更新进度。
BackgroundWorker
执行其DoWork
事件异步的注册处理程序。在工作线程上,并将已注册的处理程序运行到调用线程上的RunWorkerCompleted
事件。如果您想要在>完成异步任务后更新UI,这是理想的选择。例如在用户界面上发布完成指示
答案 2 :(得分:1)
Windows控件使用组件对象模型(COM)单线程单元(STA)模型,因为这些底层控件是单元线程的。此外,许多控件使用消息泵进行许多操作。此模型表示对每个控件的所有函数调用必须位于创建控件的同一线程上。 Invoke(和BeginInvoke和EndInvoke)封送方法调用正确的线程。
比尔瓦格纳的更有效的C#。项16.了解Windows窗体和WPF中的跨线程调用
答案 3 :(得分:0)
因为,windows表单控件是以这种方式设计的,所以只能从他们自己的线程中访问它们。正确使用异步委托可以使呼叫安全。
给定问题的实际答案包含在给定MSDN文章的第二段中=)
对Windows窗体控件的访问本质上不是线程安全的。如果有两个或多个线程操纵控件的状态,则可以强制控件进入不一致状态。其他与线程相关的错误也是可能的,例如竞争条件和死锁。确保以线程安全的方式访问控件非常重要。
你应该检查你是否可以立即访问控制,没有间接(检查InvokeRequired属性),如果你不能,你应该异步访问它(非常简化的解释:系统将等到它可以安全地访问控件)