【发布时间】:2015-01-27 12:26:02
【问题描述】:
InvokeRequired 和 Invoke 如何让我们的应用程序线程安全。
让我们考虑这样的代码:
private void ThreadSafeUpdate(string message)
{
if (this.textBoxSome.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(msg);
this.Invoke
(d, new object[] { message });
}
else
{
// It's on the same thread, no need for Invoke
this.textBoxSome.Text = message;
}
}
是否可以在
InvokeRequired之后和Invoke之前更改InvokeRequired的状态?如果不是,那为什么?Invoking 如何使其线程安全?
如果 InvokeRequired 说明是当前线程拥有控制,那么线程如何知道它是或不是所有者。
让我们考虑 SomeMethod() 当前在 Thread1 上运行。我们想从 Thread2 调用它。在内部,此方法会更新某些字段。 Method.Invoke 内部是否包含某种锁定机制?
-
如果 SomeMethod() 需要很长时间并且我们想在控件所有者线程上运行其他东西怎么办。 Invoking 会锁定所有者线程还是某种后台线程安全任务?
ThreadSafeUpdate() //takes 5 minutes in Thread2 ThreadSafeUpdate() //after 2 minutes, we are running it in other thread2 ThreadSafeUpdate() //next run from Thread3 我觉得是一种可以在winforms之外实现的通用模式,叫什么名字?
【问题讨论】:
-
1.你应该把你的问题分成多个问题。 2. 为什么你认为
Invoke使它成为线程安全的?Invoke负责在 UI 线程上排队工作,以便可以访问线程仿射的 UI 元素。 -
你应该使用事件在线程之间进行通信。
-
@user743414 您可能想要更具体一点。事件本身没有任何线程安全或跨线程。
-
@Luaan 当你必须使用 InvokeRequired 时,其他的东西是错误的(或者至少设计不好)。那是因为您正试图从另一个线程更改您的 UI 线程。 UI 线程应该仅显示数据。您的工作线程(无论他们做什么)应该直接操作数据对象而不是 UI。 UI 可以通过事件通知,例如显示修改后的数据。使数据对象线程安全应该很容易。
-
@user743414
InvokeRequired是代码异味(正如我在回答中概述的那样)。但是您的解决方案实际上并没有帮助 - 您仍然需要处理数据的正确同步。如果您的工作线程调用事件,处理程序仍将在工作线程上运行。Invoke至少确保您可以假装您的控件是演员,确保命令在单个线程上序列化。我不提倡使用Invoke。我并不是说工作线程应该直接访问 UI,但它确实需要能够以线程安全的方式将数据发送给进行 UI 更新的任何人。
标签: c# multithreading