【发布时间】:2010-10-06 15:26:23
【问题描述】:
我知道,当从任何非 UI 线程操作 UI 控件时,您必须将调用编组到 UI 线程以避免出现问题。普遍的共识是您应该使用 test InvokeRequired,如果为真,请使用 .Invoke 执行封送处理。
这导致很多代码看起来像这样:
private void UpdateSummary(string text)
{
if (this.InvokeRequired)
{
this.Invoke(new Action(() => UpdateSummary(text)));
}
else
{
summary.Text = text;
}
}
我的问题是:我可以省略 InvokeRequired 测试而只调用 Invoke,如下所示:
private void UpdateSummary(string text)
{
this.Invoke(new Action(() => summary.Text = text));
}
这样做有问题吗?如果是这样,是否有更好的方法来保留 InvokeRequired 测试,而不必到处复制和粘贴此模式?
【问题讨论】:
-
很少有线程使用的代码也可以在 UI 线程上执行。是的,当您可以使用 lambda 时,不要费心测试 InvokeRequired。
-
@Hans - 我不知道,我在控制系统工作,我有代码可以做到这一点。我经常有许多线程运行异步进程操作,除了 UI 线程之外,其中任何一个都可以调用共享日志记录、指示器更新或调用以暂停全局进程。每个线程处理进程的不同方面,但它们还必须访问某些核心方法,这些方法通过 Invoke 调用。由于本地操作员还必须通过 UI 访问其中许多方法,因此他们最终会共享大量代码。
-
InvokeRequired 仅对 UI 是必需的,不要用于其他任何事情。共享日志只需要一个锁。在软实时程序中,将上下文切换隐藏在辅助方法中是一种相当危险的反模式。
-
记录到文件,是的,但是当同时记录到屏幕或将项目添加到列表框时,它就会成为 UI 问题。许多这些动作也是整个程序的一部分。虽然在大多数情况下让工作线程通过它们并根据需要逐行调用可能会更容易让 UI 线程处理它们 - 让工作人员委托整个事情并继续他们的更多工作时间紧迫的操作。重点是,这不是不可能的情况。
-
这几乎就是我所在的船。我最终没有使用我“接受”的助手,而是保留了 InvokeRequired 测试。
标签: c# multithreading invoke invokerequired