C# 除了“其他”以外,还有什么情况;等待“;将允许中断同步代码

C# 除了“其他”以外,还有什么情况;等待“;将允许中断同步代码,c#,com,async-await,activex,rcw,C#,Com,Async Await,Activex,Rcw,我最近在异步代码中遇到了一个奇怪的错误。我在COM控件上调用了一个阻塞方法,它似乎允许异步延续在阻塞时运行 考虑示例代码(仅用于说明目的) 在正常情况下,我希望得到以下输出: Start async Start synchronous End synchronous End async 我实际上看到的是: Start async Start synchronous End async End synchronous 现在我没有COM控件的来源,但我知道这是一个非常古老的C++控件,它没有Ac

我最近在异步代码中遇到了一个奇怪的错误。我在COM控件上调用了一个阻塞方法,它似乎允许异步延续在阻塞时运行

考虑示例代码(仅用于说明目的)

在正常情况下,我希望得到以下输出:

Start async
Start synchronous
End synchronous
End async
我实际上看到的是:

Start async
Start synchronous
End async
End synchronous

现在我没有COM控件的来源,但我知道这是一个非常古老的C++控件,它没有Acsic/Acess的概念。但是,它是一个Active-X控件

我不知道.Net RCW的实现细节,但我假设必须进行某种消息泵送才能使控件工作。我还假设这个泵允许我继续运行


我的假设正确吗?以及我应该知道的任何其他情况下,我假定的同步代码可能会在哪里被中断?

无论等待与否,从
DoAsync
返回的任务在方法返回时已经开始

您使用的延迟仅为1毫秒


您尝试过更大的延迟吗?

这很正常,当呼叫跨越公寓边界时,COM将启动。它必须泵送,不这样做很可能导致死锁。不清楚为什么必须从代码段中跨越这个边界,当您谈论WPF时,它看起来像一个STA线程。可能是进程外服务器,也可能是您在工作线程上创建的对象

它与阻止STA线程时CLR对WaitOne()或Join()调用的泵送方式没有根本区别。这导致的再进入性头痛与DoEvents()引起的痛苦非常相似。但COM和CLR都是选择性地泵送,没有那么危险。尽管没有记录在案


COM单元大大简化了线程,解决了98%的常见问题。最后的2%会让你产生分裂性偏头痛,这可能是非常难以解决的,再次进入是最重要的。解决这一问题的唯一方法是不要让COM为组件提供线程安全的主页并自己处理。使用。

我知道它已经开始了,但是在它从第一个
await
返回后,它应该没有机会继续,直到我的线程点击
await任务我假设调用
DoAsync
时没有同步上下文。
Start async
Start synchronous
End async
End synchronous