IsInvokeRequired有多贵

时间:2009-03-26 18:06:55

标签: c# multithreading

是否有关于它究竟有多贵的文件:

if (x.IsInvokeRequired)
{
    beginInvoke . . . .
}
  • 如果您遇到90%的时间都在后台线程上(并因此需要),是否值得呢?
  • 如果您有一个案例,其中90%的时间都在UI线程上(因此不是必需的)是值得的吗?

围绕这一点的任何指标都会很棒。

3 个答案:

答案 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。