无论InvokeRequired如何,调用Invoke有什么问题?

时间:2009-04-14 11:56:40

标签: c# user-interface event-handling invoke invokerequired

我已经看到了交叉线程访问GUI控件的常见设置,如下所述: Shortest way to write a thread-safe access method to a windows forms control

我发现的所有网络点击都描述了类似的事情。

但是,为什么我们需要检查InvokeRequired?我们不能直接调用Invoke吗?

我认为答案是否定的,所以我真正的问题是'为什么'?

6 个答案:

答案 0 :(得分:29)

从非UI线程我们无法触及UI - 非常糟糕的事情可能发生,因为控件具有线程亲和力。因此,从非UI线程,我们必须(最小)调用InvokeBeginInvoke

但是对于UI线程,我们 想要调用Invoke很多时间;问题是如果 已经在UI线程上,它仍然有不必要的开销,即向表单的泵发送消息并进行处理。

实际上,在大多数线程代码中,您知道您希望在 -UI线程上调用特定方法,因此在这些情况下,没有额外的开销:只需拨打Invoke

答案 1 :(得分:3)

InvokeRequired基本上告诉您是否正在执行正确的线程。如果您没有使用正确的线程,则需要将任务封送到正确的线程,否则您不需要。因此需要检查。

答案 2 :(得分:1)

问题是GUI控件要求只有在用于实例化GUI控件的同一线程上执行的代码才能访问GUI控件。此要求背后的原因与Windows的架构方式有关。可以说,改变这一点很难。

InvokeRequired根据实例化线程的标识检查当前正在执行的线程的标识。如果它们相同,则代码可以自由地与控件交互。如果没有,代码必须封送从当前线程到实例化线程的数据。这是一个缓慢而昂贵的过程,如果可能的话应该避免。如果您总是调用代码,那么您的代码将会起作用,并且您可能不会注意到性能损失,但随着多核系统的投入使用,这种情况将越来越普遍。最好不要创建必须在以后撤消的代码“结”。

答案 3 :(得分:1)

如果在创建窗口句柄之前尝试调用(例如,在调用表单构造函数时),则会得到InvalidOperationException。因此,通常需要进行InvokeRequired检查。

有关详细信息,请参阅MSDN

答案 4 :(得分:0)

Invoke将通过Delegate调用代码,而不是直接调用代码。

仅在需要时调用Invoke才有效。因此,InvokeRequired用于查找是从同一个线程还是另一个线程进行的调用?

答案 5 :(得分:0)

我能想到的一个原因是表现。 如果大多数时候调用线程与创建线程相同,那么你将有一些未加密的开销。