C# 等待不会在原始上下文中恢复
C# 等待不会在原始上下文中恢复,c#,wpf,async-await,C#,Wpf,Async Await,wait由于某种原因,似乎无法在调用上下文上恢复。我正在调用一个async方法(实际上是几个async方法的层次结构)。一切顺利,直到我最终到达使用RestSharp的ExecuteAsync()的数据服务。最后一个电话是这样的: IRestResponse Response = await rc.ExecuteAsync(request); //rc is a RestClient object 我已经对它进行了彻底的调试,在每个级别上,甚至在调用ExecuteAsync之前,下一行都返回t
wait
由于某种原因,似乎无法在调用上下文上恢复。我正在调用一个async
方法(实际上是几个async
方法的层次结构)。一切顺利,直到我最终到达使用RestSharp的ExecuteAsync()
的数据服务。最后一个电话是这样的:
IRestResponse Response = await rc.ExecuteAsync(request); //rc is a RestClient object
我已经对它进行了彻底的调试,在每个级别上,甚至在调用ExecuteAsync
之前,下一行都返回true
:
System.Threading.Thread.CurrentThread == System.Windows.Application.Current.Dispatcher.Thread
只有在ExecuteAsync()
返回服务器数据后,上述行才会变为false
,表明上述wait
未在调用线程上恢复。因此,调用此异步操作并希望将返回的数据分配给UI的高层抛出臭名昭著的STA线程异常
我做错了什么?我已经花了好几个小时,浏览了好几篇SO帖子和网络文章,但这似乎不起作用。我还添加了ConfigureAwait(true)
,明确要求它在调用上下文时恢复,但它没有
这是一个VSTO Word加载项。我正在使用WPF
这是一个VSTO Word加载项
这实际上是问题的根源
wait
捕获的实际“上下文”是SynchronizationContext.Current
(除非它是null
,在这种情况下它是TaskScheduler.Current
)。WinForms和WPF等UI应用程序提供了自己的SynchronizationContext
,这就是在UI线程上等待
恢复的方式
除了Office插件。我不知道为什么,但它们不提供同步上下文。因此,如果要在Office加载项中使用wait
,则需要提供SynchronizationContext
我相信基于WPF的Office插件能够在每次async
事件开始时做到这一点:
SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext());
但我从未真正尝试过这一点 两个相关问题:1。是否需要在每次等待之前设置同步上下文,还是可以在启动外接程序时设置一次?2.我是否可以以某种方式获取WPF的内置/默认同步上下文,还是必须像
newdispatchersynchronizationcontext()
那样进行?(我查看了libs,得到的最接近的东西是System.Windows.Application.Current.Dispatcher
,但它不允许我访问上下文对象)。我想你可以只做一次,但你需要测试一下才能确定。2.我不知道怎么做。但我不会为此担心;上次我检查时,WPF本身将使用多个SyncCtx实例,这些实例都引用同一个调度程序(每个顶级窗口IIRC一个)。