代码之家  ›  专栏  ›  技术社区  ›  MattH

调用invoke有什么问题,不管invokeRequired如何?

  •  34
  • MattH  · 技术社区  · 16 年前

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

    我找到的所有网站都描述了类似的事情。

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

    我想答案是否定的,所以我真正的问题是“为什么”?

    6 回复  |  直到 9 年前
        1
  •  28
  •   Marc Gravell    16 年前

    在非UI线程中,我们不能接触到UI——可能会发生非常糟糕的事情,因为控件具有线程关联性。因此,从非UI线程,我们必须(至少)调用 Invoke BeginInvoke .

    但是,对于UI线程,我们 不要 想打电话 援引 很多时间,问题是如果你 在UI线程上,它仍然有不必要的开销,即向表单的泵发送消息并对其进行处理。

    实际上,在大多数线程代码中, 知道 您希望在 -UI线程,因此在这些情况下,没有额外的开销:只需调用 援引 .

        2
  •  3
  •   Brian Rasmussen    16 年前

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

        3
  •  1
  •   JonStonecash    16 年前

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

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

        4
  •  1
  •   Dmitry Fedorkov    9 年前

    如果在创建窗口句柄之前尝试调用(例如,在调用窗体构造函数时),您将得到 InvalidOperationException . 所以,一般来说 InvokeRequired 需要检查。

    MSDN 详情。

        5
  •  0
  •   user88637    16 年前

    我能想到的一个原因是表演。 如果大多数时候调用线程与创建线程相同,那么您将有一些不必要的开销。

        6
  •  0
  •   NileshChauhan    16 年前

    调用将通过委托来调用代码,而不是直接调用,这将是昂贵的。

    只有在需要时才调用invoke,这是一种成本效益。因此,invokeRequired用于确定调用是来自同一线程还是来自另一线程?