首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Invoke和BeginInvoke

Invoke和BeginInvoke
EN

Stack Overflow用户
提问于 2009-12-16 03:38:19
回答 5查看 17.5K关注 0票数 18

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

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

代码语言:javascript
运行
复制
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会等待其执行完成。我感兴趣的最重要的情况是为什么在这种情况下刷新标签文本会有差异。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-12-16 03:44:12

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

使用BeginInvoke时,方法是异步调用的,在执行BeginInvoke中引用的方法时,应用程序将继续执行。

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

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

希望这能有所帮助!

票数 8
EN

Stack Overflow用户

发布于 2009-12-16 03:44:15

首先,从你的链接开始:

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

和来自MSDN的:

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

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

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

票数 19
EN

Stack Overflow用户

发布于 2010-02-10 20:53:21

Control.BeginInvoke不能在不同的线程(或线程池)上工作,而delegate.BeginInvoke可以。MSDN的one liner表示:

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

然而,Control.BeginInvoke只是简单地使用PostMessage并返回-没有创建任何CLR Thread

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

This article总结了是否很好地使用InvokeBeginInvoke

你会问

要使用哪个函数。这真的取决于你的需求。如果希望在继续之前完成UI更新,可以使用Invoke。如果没有这样的要求,我建议使用BeginInvoke,因为它使调用它的线程看起来“更快”。尽管如此,BeginInvoke还是有一些问题。

  • 如果您通过BeginInvoke调用的函数访问共享状态(在UI线程和其他线程之间共享的状态),那么您就有麻烦了。在调用BeginInvoke和实际执行包装函数之间,状态可能会发生变化,从而导致很难发现计时问题。
  • 如果要通过BeginInvoke将引用参数传递给调用的函数,则必须确保在函数完成之前没有其他人修改传递的对象。通常,人们会在将对象传递给BeginInvoke之前对其进行克隆,这样就完全避免了这个问题。
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1909839

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档