TL; DR:运行任务中的死锁StaTaskScheduler.长版:
我使用的是StaTaskScheduler从ParallelExtensionsExtras中通过平行小组,举办由第三方提供的一些遗留STA COM对象.StaTaskScheduler实现细节的描述如下:
好消息是TPL的实现能够在MTA或STA线程上运行,并考虑到底层API的相关差异,如WaitHandle.WaitAll(当方法提供多个等待句柄时,它只支持MTA线程).
我认为这意味着TPL的阻塞部分将使用等待API来提供消息,例如CoWaitForMultipleHandles,以避免在STA线程上调用时出现死锁情况.
在我的情况下,我相信发生以下情况:进程内STA COM对象A调用进程外对象B,然后期望从B通过回调作为传出调用的一部分.
以简化形式:
var result = await Task.Factory.StartNew(() =>
{
// in-proc object A
var a = new A();
// out-of-proc object B
var b = new B();
// A calls B and B calls back A during the Method call
return a.Method(b);
}, CancellationToken.None, TaskCreationOptions.None, staTaskScheduler);
Run Code Online (Sandbox Code Playgroud)
问题是,a.Method(b)永远不会回来.据我所知,这是因为内部阻塞等待BlockingCollection<Task>不会引发消息,因此我对引用语句的假设可能是错误的.
EDITED相同的代码工作测试WinForms应用程序的UI线程上执行时(即,提供TaskScheduler.FromCurrentSynchronizationContext()的,而不是staTaskScheduler到Task.Factory.StartNew).
解决这个问题的正确方法是什么?我应该实现一个自定义同步上下文,它将显式地使用消息CoWaitForMultipleHandles …
对于WPF应用程序,内部是否存在经典的消息循环(在Windows中GetMessage/DispatchMessage)Application.Run?是否可以使用PostThreadMessage将另一个Win32应用程序发布的消息捕获到WPF UI线程(没有HWND句柄的消息).谢谢.