根据我的理解,Dispatcher.Invoke和Dispatcher.BeginInvoke在UI线程上执行,唯一的区别是调用是同步的,而BeginInvoke是asynchronous.My问题是当我使用这段代码时。
EDisc.App.Current.Dispatcher.
Invoke(
DispatcherPriority.Normal, new Action(delegate
{
context = NavigationManager.CurrentPage.DataContext;
}));返回上下文的值。但是,使用下面的代码
EDisc.App.Current.Dispatcher.
BeginInvoke(
DispatcherPriority.Normal, new Action(delegate
{
context = NavigationManager.CurrentPage.DataContext;
}));上下文为null,我得到一个InvalidOperation异常,表示“
调用线程无法访问这个对象,因为另一个线程拥有它,我从一个使用UseSynchronizationContext = false .Can执行的WCF服务调用它,有人解释了这种行为吗?
发布于 2010-12-14 11:13:55
BeginInvoke和Invoke都将调用一个名为BeginInvokeImpl的内部方法来完成这项工作。不同的是,Invoke在返回之前等待操作完成。
还有一个不同之处:如果您已经在UI线程上,并且正在使用DispatcherPriority.Send,那么Invoke实际上将直接调用该方法,而不通过BeginInvokeImpl调用,这意味着操作是在不经过消息队列的情况下处理的。(如果您不使用Send,那么将首先处理任何其他具有比操作更高属性的消息。)
但是,由于您可能不在这里的UI线程上--您正在进行一些WCF回调--这种特殊情况将不适用。因此,Invoke最终会调用与BeginInvoke相同的底层实现。
从你提供的信息来看,我不得不猜测这里缺少一个细节。您所展示的代码应该可以正常工作,除非您的应用程序中可能有多个UI线程,并且碰巧位于CurrentPage中的页面不时属于不同的线程。
如果您确实有多个UI线程,那么您所使用的方法--通过当前Application对象的dispatcher来推送所有东西--将无法工作,因为您将有多个dispatcher。您需要为您计划接触的任何UI元素获得正确的dispatcher。
顺便说一句,如果您在某个工作线程或回调上构造一个UI对象(例如,Page),您可能会意外地得到多个UI线程。你有可能在什么地方做过这种事吗?
https://stackoverflow.com/questions/4436808
复制相似问题