我有更多关于这个问题的信息(我和 mikecamimo 在同一个团队工作)。
如果正确复制,该问题也会出现在 Windows 窗体应用程序中。在原来的 OP 中,由于没有阻塞,所以在 windows 窗体中没有出现问题。当使用 ResetEvent 引入阻塞时,会出现同样的问题。
这是因为事件处理程序 (Widget_Completed) 与调用 Widget.DoWork 的方法位于同一线程上。AutoResetEvent.WaitOne(); 的结果 永远阻塞,因为永远不会调用事件处理程序来设置事件。
在 Windows 窗体环境中,这可以通过使用 Application.DoEvents 轮询消息队列并允许处理事件来解决。见下文。
using System;
using System.Threading;
using System.Windows.Forms;
class Program
{
EventArgs data;
static void Main()
{
Program p = new Program();
p.RunWidget();
}
public Program()
{
_autoEvent = new AutoResetEvent(false);
}
public void RunWidget()
{
ThirdParty widget = new ThirdParty();
widget.Completed += new EventHandler(this.Widget_Completed);
data = null;
widget.DoWork();
while (data == null);
Application.DoEvents();
// do stuff with the results of DoWork that are contained in EventArgs.
}
// Assumes that some kind of args are passed by the event
public void Widget_Completed(object sender, EventArgs e)
{
data = e;
}
}
在非 Windows 窗体应用程序(例如 Windows 服务)中,应用程序不可用,因此无法调用 DoEvents。
问题是线程之一,widget.DoWork 的关联事件处理程序不知何故需要在另一个线程上。这应该可以防止 AutoResetEvent.WaitOne 无限期地阻塞。我认为... :)
关于如何实现这一点的任何想法都会很棒。