考虑以下情况:
我在本机API(P / Invoke)的顶部创建了一个托管包装。
该API运行USB设备,在专用线程上执行I / O操作。
此外,此API是单线程的,因此调用其方法并最终确定它必须在已初始化它的同一线程上完成。
它的要点是:
//Runs in the context of a new System.Threading.Thread instance
void Loopback()
{
InitializeAPI();
try
{
while(_work)
{
//Poll API
}
}
finally
{
FinalizeAPI()
//Unblock disposing thread
}
}
void Dispose()
{
_work=false;
//Block untill Loopback method returns
}
在WPF应用程序的上下文中使用上述包装器时,我在Application.OnExit覆盖中调用我的包装器类的Dispose方法。这会导致死锁。
单击VS中的Thread窗口,可以清楚地看到专用于本机API的工作线程停留在与当前WPF Dispatcher关联的某个等待句柄上。我想这是有道理的,因为WPF希望在最终确定时暂停所有内容。
另一方面,我的Dispose方法 - 在设备的API完成之前不得返回,所以当专用线程完成时,我连接了一个TaskCompletionSource来完成它的任务。
我的Dispose方法的作用是通过切换循环条件变量并立即阻止TaskCompletionSource的任务来启动线程的结束。
专用线程永远不会完成,因为它被WPF阻止,并且UI线程永远不会完成,因为它阻塞了永远不会完成的任务,因此死锁。
有没有办法克服这个问题,同时保持与包装器端的客户端框架无关?
非常感谢帮助!