我们有一些代码在后台线程中运行,需要弹出对话框或其他一些用户交互,所以我们Invoke
对 UI 线程进行通常的调用:
Control.Invoke(SomeFunction);
void SomeFunction()
{
...
}
但是,我们遇到了一个错误,我们的 UI 线程有时没有立即响应Invoke
调用 - 我们跟踪到 UI 线程当前正在执行尚未返回的跨进程 DCOM 调用这一事实。一旦 DCOM 调用返回,我们的函数就会被调用,但在那之前,Invoke
调用似乎已经挂起。
我对此的解决方案是引入超时:
ManualResetEvent invokeEvent = new ManualResetEvent();
var result = Control.BeginInvoke(SomeFunction, invokeEvent);
if (!invokeEvent.WaitOne(1000))
throw new Exception("Not responding");
Control.EndInvoke(result);
void SomeFunction(ManualResetEvent invokeEvent)
{
invokeEvent.Set();
...
}
这在“我的机器意义上的作品”中有效,但它有许多缺陷。
(来源:codinghorror.com)
- 首先,即使发生超时,该函数仍然会被调用——如果 DCOM 调用实际上没有完全挂起,它最终会运行
- 其次,有明显可怕的比赛条件
- 最后,整个事情的整体“Arrgh”-ness
即使前两件事可以解决,我们仍然有普遍的恶心。有没有更好的方法来解决这个问题?