我知道当从任何非UI线程操作UI控件时,您必须将调用编组到UI线程以避免出现问题。一般的共识是您应该使用测试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测试,而不必到处复制和粘贴这个模式?
发布于 2010-10-06 23:29:52
好吧,这样如何:
public static class ControlHelpers
{
public static void InvokeIfRequired<T>(this T control, Action<T> action) where T : ISynchronizeInvoke
{
if (control.InvokeRequired)
{
control.Invoke(new Action(() => action(control)), null);
}
else
{
action(control);
}
}
}
像这样使用它:
private void UpdateSummary(string text)
{
summary.InvokeIfRequired(s => { s.Text = text });
}
发布于 2010-10-06 23:29:46
从UI线程调用Invoke
的效率有点低。
相反,您可以创建一个接受Action
参数的InvokeIfNeeded
扩展方法。(这也允许您从调用站点中删除new Action(...)
)
发布于 2010-10-07 02:32:55
我一直在阅读关于添加逻辑检查的来回参数,以确定当不在UI线程和UI线程本身上时是否应该使用invoke。我写了一个类,检查执行(通过秒表)各种方法的时间,以获得一个方法相对于另一个方法的效率的粗略估计。
结果可能会让你们中的一些人感到惊讶(这些测试是通过Form.Shown事件运行的):
// notice that we are updating the form's title bar 10,000 times
// directly on the UI thread
TimedAction.Go
(
"Direct on UI Thread",
() =>
{
for (int i = 0; i < 10000; i++)
{
this.Text = "1234567890";
}
}
);
// notice that we are invoking the update of the title bar
// (UI thread -> [invoke] -> UI thread)
TimedAction.Go
(
"Invoke on UI Thread",
() =>
{
this.Invoke
(
new Action
(
() =>
{
for (int i = 0; i < 10000; i++)
{
this.Text = "1234567890";
}
}
)
);
}
);
// the following is invoking each UPDATE on the UI thread from the UI thread
// (10,000 invokes)
TimedAction.Go
(
"Separate Invoke on UI Thread",
() =>
{
for (int i = 0; i < 10000; i++)
{
this.Invoke
(
new Action
(
() =>
{
this.Text = "1234567890";
}
)
);
}
}
);
结果如下:
调试:在UI线程上直接调试秒表:300ms
我的结论是,无论您是在UI线程上还是在工作线程上,您都可以在任何时候安全地调用,而不会产生通过消息泵循环返回的大量开销。但是,在UI线程上执行大部分工作,而不是对UI线程进行大量调用(通过Invoke())是有利的,并且可以极大地提高效率。
https://stackoverflow.com/questions/3874134
复制相似问题