[英]await does not resume on main thread
I faced this problem a couple of years ago and got this very helpful answer from Stephen Cleary.几年前我遇到了这个问题,并从 Stephen Cleary 那里得到了这个非常有用的答案。 Problem with VSTO add-ins is that they do not set a SynchronizationContext
and therefore async calls do not resume on UI thread, causing all sorts of cross-thread access troubles. VSTO 加载项的问题是它们没有设置SynchronizationContext
,因此异步调用不会在 UI 线程上恢复,从而导致各种跨线程访问问题。 The solution, as he mentioned is to manually call SetSynchronizationContext
before calling any async
function.正如他提到的,解决方案是在调用任何async
function 之前手动调用SetSynchronizationContext
。
I have been using this technique since then and thought that was all there was to it.从那时起我就一直在使用这种技术,并认为这就是它的全部。 But today I have seen a situation where even manually setting the context does not force it to resume on calling thread.但是今天我看到了一种情况,即使手动设置上下文也不会强制它在调用线程上恢复。
My VSTO add-in contains a WPF pane (inside a CustomTaskPane) which is bound to its ViewModel that contains several AsyncRelayCommand
properties (from WCT).我的 VSTO 加载项包含一个 WPF 窗格(在 CustomTaskPane 内),它绑定到包含多个AsyncRelayCommand
属性(来自 WCT)的 ViewModel。 One of these commands calls my Data Service which in turn calls a RestSharp methods to fetch data from the API server.其中一个命令调用我的数据服务,后者又调用 RestSharp 方法从 API 服务器获取数据。
All these calls use async
/ await
and all these call use ConfigureAwait(false)
except the one at the top level (ie the command itself).所有这些调用都使用async
/ await
并且所有这些调用都使用ConfigureAwait(false)
除了顶层的调用(即命令本身)。 Here is a snapshot of how this call-site looks like:下面是这个调用站点的快照:
As you can see, I have manually called SetSynchronizationContext
before doing the await
call.如您所见,我在执行await
调用之前手动调用SetSynchronizationContext
。 It also shows that SynchronizationContext.Current
is set after it resumes after the await call, but somehow the code is still running on the worker thread.它还显示SynchronizationContext.Current
在 await 调用后恢复后设置,但不知何故代码仍在工作线程上运行。 I also verified that the code was running on UI thread when it hit line 259 before drilling down into the await
call.我还验证了代码在到达第 259 行时正在 UI 线程上运行,然后再深入到await
调用。
I have already spent a lot of time and effort on this and can't make any sense of it.我已经在这上面花了很多时间和精力,但无法理解它。 Can anyone help me figure out if I'm missing something obvious?谁能帮我弄清楚我是否遗漏了一些明显的东西?
You need to use an instance of the WindowsFormsSynchronizationContext class instead.您需要改用WindowsFormsSynchronizationContext class 的实例。
The WindowsFormsSynchronizationContext
class provides a synchronization mechanism for Windows Forms. WindowsFormsSynchronizationContext
class提供了Windows Forms的同步机制。
The DispatcherSynchronizationContext
class is for WPF applications which uses two threads. DispatcherSynchronizationContext
class 适用于使用两个线程的 WPF 应用程序。 One thread is background thread for rendering and the other thread is for UI.一个线程是用于渲染的后台线程,另一个线程用于 UI。 So, UI elements in one thread are not accessible to other UI threads.因此,其他 UI 线程无法访问一个线程中的 UI 元素。 Microsoft introduced the dispatcher which is responsible for multiple UI threads interaction. Microsoft 引入了负责多个 UI 线程交互的调度程序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.