18

您好,我正在用 C# 开发一些应用程序。目前我正在处理线程,我有一个问题在我脑海中。Invoke 和 BeginInvoke 有什么区别?我阅读了一些帖子,并在这里找到了一些有用的信息:这里

但是,以下代码中的 Invoke 和 BeginInvoke 有什么区别:

private void ProcessRoutine()
{
   for (int nValue = StartFrom; nValue <= EndTo; nValue++)
   {
      this.Invoke(this.MyDelegate, nValue);
      //this.BeginInvoke(this.MyDelegate, nValue);
   }
   MessageBox.Show("Counting complete!");
}
private void MessageHandler(int progress)
{
    lblStatus.Text = lblStatus.Text = "Processing item: " + progress.ToString();
    progressBar1.Value = progress;
}

其中 MyDelegate 是对 MessageHandler 函数的引用。

我注意到使用 BeginInvoke lblStatus.Text 不会刷新使用 Invoke 刷新标签的位置。此外,我知道 Invoke 等待其执行完成。我感兴趣的最重要的案例是为什么在这种情况下刷新标签文本会有所不同。

4

5 回答 5

19

首先,从您的链接:

  • Control.Invoke:在 UI 线程上执行,但调用线程在继续之前等待完成。
  • Control.BeginInvoke: 在异步 UI 线程上执行,调用线程不等待完成。

并来自 MSDN:

BeginInvoke 在创建控件的基础句柄的线程上异步执行指定的委托。

总结一下,BeginInvoke就是异步。当BeginInvoke从 UI 线程调用时,请求将与 UI 线程并行执行。这意味着它可能在当前执行的方法返回之前不会执行。因此在这种情况下,文本框将永远不会更新,因为 for 循环不会被中断,因为调用线程不会等待此事件完成后再继续。

或者,Invoke同步的。文本框将被更新,因为调用线程将在继续执行之前等待调用完成。

于 2009-12-15T19:44:15.267 回答
8

使用 Invoke 方法被执行,应用程序等待它完成。

使用 BeginInvoke,该方法被异步调用,应用程序继续执行,同时执行 BeginInvoke 中引用的方法。

使用 BeginInvoke,您需要调用 EndInvoke 以获取您使用 BeginIvnoke 执行的方法的结果。

您不应该更新 BeginXXX 方法中的 GUI 组件,因为它们在 GUI 线程的另一个线程中运行,这与您的 Invoke 方法相反。您不能在与 GUI 线程不同的线程中访问 GUI 组件。

希望这可以帮助!

于 2009-12-15T19:44:12.133 回答
6

Control.BeginInvoke不能在不同的线程(或线程池)上工作,delegate.BeginInvoke 可以。MSDN 的一个班轮说:

在创建控件的基础句柄的线程上异步执行指定的委托。

然而,Control.BeginInvoke只需使用PostMessage并返回 - 没有创建 CLR Thread

PostMessage 函数将消息放置(发布)到与创建指定窗口的线程相关联的消息队列中,并在不等待线程处理消息的情况下返回。

这篇文章总结了是否使用InvokeBeginInvoke相当好:

你问使用哪个功能。这真的取决于你的要求。如果您希望在继续之前完成 UI 更新,请使用 Invoke。如果没有这样的要求,我建议使用 BeginInvoke,因为它使调用它的线程看起来“更快”。不过 BeginInvoke 有一些问题。

  • 如果您通过 BeginInvoke 调用的函数访问共享状态(UI 线程和其他线程之间共享的状态),您就有麻烦了。在您调用 BeginInvoke 和包装函数实际执行之间,状态可能会发生变化,从而导致难以发现计时问题。
  • 如果您将引用参数传递给通过 BeginInvoke 调用的函数,那么您必须确保在函数完成之前没有其他人修改传递的对象。通常,人们在将对象传递给 BeginInvoke 之前对其进行克隆,从而完全避免了该问题。
于 2010-02-10T12:53:20.993 回答
1

BeginInvoke 在另一个线程上执行方法体并允许当前线程继续。如果您尝试直接从另一个线程更新控件属性,它将引发异常。

于 2009-12-15T19:42:53.337 回答
0

这基本上归结为您是否希望控件同步或异步更新。这一切都取决于您的具体情况。

于 2009-12-15T19:43:50.637 回答