是否有关于它究竟有多贵的文件:
if (x.IsInvokeRequired)
{
beginInvoke . . . .
}
围绕这一点的任何指标都会很棒。
答案 0 :(得分:5)
使用分析器
我认为您需要考虑两个函数的相对成本与InvokeRequired的绝对成本。
InvokeRequired for Control基本上将当前的ThreadId与预期的ThreadId进行比较。如果你看反射器,代码会稍微复杂一点,但实际上它就是它正在做的事情。这是相当便宜的,因为它只是一些函数调用和比较。
BeginInvoke涉及获取多个锁,将委托添加到调用队列,并可能在线程之间添加一个元帅。相对于实际的InvokeRequired调用,此代码要昂贵得多(可能是一个数量级或2)。你需要更多的调用,其中InvokeRequired返回true,然后你才会看到任何增益直接进入BeignInvoke。
答案 1 :(得分:3)
没有指标,但快速进入Reflector会告诉我们这个电话很可能根本不是很贵:
[SRDescription("ControlInvokeRequiredDescr"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced)]
public bool InvokeRequired
{
get
{
using (new MultithreadSafeCallScope())
{
HandleRef ref2;
int num;
if (this.IsHandleCreated)
{
ref2 = new HandleRef(this, this.Handle);
}
else
{
Control wrapper = this.FindMarshalingControl();
if (!wrapper.IsHandleCreated)
{
return false;
}
ref2 = new HandleRef(wrapper, wrapper.Handle);
}
int windowThreadProcessId = SafeNativeMethods.GetWindowThreadProcessId(ref2, out num);
int currentThreadId = SafeNativeMethods.GetCurrentThreadId();
return (windowThreadProcessId != currentThreadId);
}
}
}
无论使用情况如何,最好进行检查,因为这种微优化的任何性能提升都会被问题突然出现的风险所抵消。
答案 2 :(得分:2)
InvokeRequired的开销取决于实现ISynchronizeInvoke的类和具体的用例。 “成本”将取决于您使用的实施。但是,一般来说,它通常是一个相当低的开销呼叫。 (在许多情况下,它可以像检查当前线程是否与原始线程一样简单。)
话虽如此,如果你需要它,它值得花费,总是。即使它只需要1%的时间,也应包括在内。否则,您要求崩溃,锁定或其他一些非常不良的行为。大多数情况下,您可以使用此功能的情况下,您应始终包含此费用。
最常见的用例是将委托同步到UI线程。在这种情况下,您必须使用它,或者发生非常糟糕的事情......此外,在这种情况下,与等待消息泵进行UI交互相比,成本非常低,所以它真的不值得担心。
如果您正在使用ISynchronizeInvoke的自定义实现,并且它正在紧密循环中发生,并且您已经分析并发现它对您造成了问题,那么它可能值得担心。但是,在这种情况下,我建议尝试重新编写算法本身以避免尽可能多地进行同步,但仍然根据需要使用InvokeRequired。