问题描述
|
从工作线程调用UI线程的讨论很多次,我们知道为什么要使用BeginInvoke()而不是Invoke()。我最近发布了这个问题,经过研究后发现,至少有三种不同的方法(内部可能是相同的)来调用(异步)UI线程上的某些东西。
Control.BeginInvoke()
使用SynchronizatoinContext
课
使用Dispatcher.BeginInvoke(priority.. )
谁能告诉我哪种方法是异步调用要在UI线程上执行的方法的可靠方法。有经验吗?我看到Dispatcher.BeginInvoke具有优先级组件,它使它更可靠吗?
内容:
我们使用的是someControl.BeginInvoke()
,但注意到有时(不幸的是,仅在最终用户生产环境中)传递给BeginInvoke is
的委托从未执行,这使我相信它所创建的发布消息会丢失。我们想要一种可靠的方法来与UI线程通信。 control.Invoke()
有时会挂起UI,所以我们也不想去那里。
解决方法
它们都按应有的方式工作,如果您呼叫
BeginInvoke
,有时什么也没发生,则环境或调用代码中可能存在一些问题-BeginInvoke
不是不可靠。好吧-可能有一个错误,但是可能性很小。
也许您可以提供更多背景信息,我们可以帮助您进行诊断。
, 在更多情况下,SynchronizationContext更抽象且更具适应性。它是特定实现的包装。
MSDN说:“同步模型的提供者可以扩展此类,并为这些方法提供自己的实现”。
, 您应谨慎使用lambda函数和BeginInvoke。我有这样的代码,导致各种奇怪的行为。
MyThing thing;
while( GetThing(ref thing)) {
control.BeginInvoke((Action)(() => control.Text = thing.ToString()));
}
问题在于创建lambda函数时不会评估ѭ9。当执行lamdba函数时将对其进行评估。但是它绑定到在生产者线程中同时更改的变量。
您可以通过声明局部变量ѭ9来解决此问题。
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()));
}