2011-06-13 48 views
6

从工作者线程调用UI线程讨论了很多次,我们知道为什么要使用BeginInvoke()而不是Invoke()。我最近发布了this question,在做了一些研究之后,我发现至少有三种不同的方式(在内部它们可能是相同的)在UI线程上调用(异步)某些东西。control.BeginInvoke()VS Dispatcher VS SynchronizationContext VS. - 可靠性

  1. Control.BeginInvoke()
  2. 使用SynchronizatoinContext
  3. 使用Dispatcher.BeginInvoke(priority..)

谁能告诉我这是一个可靠的方法来异步调用要在UI线程执行的方法。任何经验?我看到Dispatcher.BeginInvoke具有优先组件,它是否更加可靠?

语境
我们使用someControl.BeginInvoke(),但注意到,有时候(可惜只有在最终用户生产环境)的委托传递给BeginInvoke is永远不会执行这让我相信,它会创建到请求消息迷路。我们需要一种可靠的方式来回传给UI线程。 control.Invoke()有时会挂起UI,因此我们不想去那里。

+0

不要混淆WPF的WinForms。 – SLaks 2011-06-13 15:22:36

+0

我遇到了类似的问题......您是否有机会纠正这个问题? – 2011-11-23 22:44:42

+0

同样在这里,有没有更新? – Pedro77 2013-06-17 17:28:03

回答

0

他们都按照他们应该的方式操作,如果您拨打BeginInvoke并且有时没有任何反应,那么环境或调用代码中可能存在问题 - 可能并非BeginInvoke不可靠。那么 - 可能有一个错误,但它可能性很小。

也许你可以给更多的上下文,我们可以帮助诊断。

+0

感谢您的回应。我在我们的代码中有类似的情况。 http://stackoverflow.com/questions/6270514/control-begininvoke-fails-to-call-the-delegate – karephul 2011-06-13 15:18:27

+0

嗨karephul,这很有趣,但在这种情况下没有什么帮助,因为他们没有找到答案。你在线程,进程,锁等方面的基本设置是什么? – 2011-06-13 15:27:49

+0

哦......是这个问题吗?刚在这里转贴? – 2011-06-13 15:28:24

0

SynchronizationContext在更多情况下更具抽象性和适应性。它是具体实现的包装。 MSDN说“同步模型的提供者可以扩展这个类并为这些方法提供它们自己的实现”。

+0

SynchronizationContext优先于此处:http://social.msdn.microsoft.com/Forums/en-US/async/thread/1218c86e-fa9b-45a6-93b0-5e27616a6c21 – Steel 2012-12-13 05:22:09

0

你应该小心使用lambda函数和BeginInvoke。我有这样的代码导致了各种奇怪的行为。

MyThing thing; 
while(GetThing(ref thing)) { 
    control.BeginInvoke((Action)(() => control.Text = thing.ToString())); 
} 

问题是,当您创建lambda函数时,不会评估thing。它在lamdba函数执行时进行评估。但它绑定到一个在生产者线程中同时发生变化的变量。

可以通过声明的thing

MyThing thing; 
while(GetThing(ref thing)) { 
    MyThing thing_x = thing; 
    control.BeginInvoke((Action)(() => control.Text = thing_x.ToString())); 
} 

一个局部变量副本解决这个问题,或者你可以把丑陋的BeginInvoke在包装

MyThing thing; 
while(GetThing(ref thing)) { 
    SetText(thing); 
} 

void SetText(MyThing thing) 
    control.BeginInvoke((Action)(() => control.Text = thing.ToString())); 
}