【发布时间】:2011-07-11 21:18:45
【问题描述】:
任何时候初学者问类似:How to update the GUI from another thread in C#?,答案都很直接:
if (foo.InvokeRequired)
{
foo.BeginInvoke(...)
} else {
...
}
但是真的好用吗?在非 GUI 线程执行 foo.InvokeRequired 之后,foo 的状态可以改变。例如,如果我们在foo.InvokeRequired 之后但在foo.BeginInvoke 之前关闭窗体,则调用foo.BeginInvoke 将导致InvalidOperationException:在创建窗口句柄之前,不能在控件上调用Invoke 或BeginInvoke。 如果我们在调用InvokeRequired 之前关闭表单就不会发生这种情况,因为即使从非GUI 线程调用它也会是false。
另一个例子:假设foo 是TextBox。如果您关闭表单,并且在该非 GUI 线程执行 foo.InvokeRequired(这是错误的,因为表单已关闭)和 foo.AppendText 之后,它将导致 ObjectDisposedException。
相比之下,在我看来,使用WindowsFormsSynchronizationContext 更容易——只有当线程仍然存在时才会使用Post 发布回调,如果线程不再存在,使用Send 的同步调用会抛出InvalidAsynchronousStateException。
使用WindowsFormsSynchronizationContext 不是更简单吗?我错过了什么吗?如果 InvokeRequired-BeginInvoke 模式不是真正的线程安全,为什么要使用它?你觉得哪个更好?
【问题讨论】:
标签: c# .net winforms synchronization multithreading