首页 文章

Invoke和BeginInvoke

提问于
浏览
16

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

但是,以下代码中的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等待它的执行完成 . 我感兴趣的最重要的案例是为什么在这种情况下刷新标签文本会有所不同 .

5 回答

  • 19

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

    使用BeginInvoke,方法被Asychnronously调用,应用程序继续执行,同时执行BeginInvoke中引用的方法 .

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

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

    希望这可以帮助!

  • 0

    首先,从您的链接:

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

    • Control.BeginInvoke :在异步UI线程上执行,调用线程不等待完成 .

    从MSDN:

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

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

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

  • 7

    Control.BeginInvoke 不是't work on a different thread (or threadpool), a delegate.BeginInvoke does. MSDN'的一个班轮说:

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

    但是 Control.BeginInvoke 只是使用PostMessage并返回 - 没有创建CLR Thread .

    PostMessage函数将消息放入(发布)与创建指定窗口的线程关联的消息队列中,并返回而不等待线程处理消息 .

    This article总结了是否使用 InvokeBeginInvoke

    你问哪个功能 . 这真的取决于你的要求 . 如果您希望在继续之前完成UI更新,则使用Invoke . 如果没有这样的要求,我建议使用BeginInvoke,因为它使得调用它的线程看起来“更快” . 但是有一些关于BeginInvoke的问题 . 如果您通过BeginInvoke调用的函数访问共享状态(UI线程和其他线程之间共享的状态),则表示您遇到了麻烦 . 状态可能会在您调用BeginInvoke和实际执行包装函数之间发生变化,从而导致很难找到计时问题 . 如果要将引用参数传递给通过BeginInvoke调用的函数,则必须确保在函数完成之前没有其他人修改传递的对象 . 通常,人们在将对象传递给BeginInvoke之前克隆该对象,这完全避免了这个问题 .

  • 5

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

  • 1

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

相关问题