简体   繁体   English

等待不会在主线程上恢复

[英]await does not resume on main thread

Background背景

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.但是今天我看到了一种情况,即使手动设置上下文也不会强制它在调用线程上恢复。

Situation情况

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM