阻塞的线程可以触发事件吗?

Can a blocked thread fire events?

我有一个程序生成一个控制串行通信的线程。当它等待串行端口上的响应时,我用 AutoResetEvent 阻塞了线程。

那个线程收到数据会不会因为被阻塞而无法执行事件?

为了说明这一点,我在下面有一个简单版本的代码。此代码是否会导致死锁或阻塞线程中的事件 运行 最终会自行唤醒?

AutoResetEvent rxDataReady = new AutoResetEvent(false);

public void GetSomeDataFromSerialPort()
{
    SerialPort sp = new SerialPort()
    sp.Write(dataRequest)

    rxDataReady.WaitOne();

    // Process data
}

private void ReadDataEventHandler(object sender, SerialDataReceivedEventArgs e)
{
    // Prepare data
    rxDataReady.Set();
}

非常感谢

来自MSDN的评论SerialPort.DataReceived

The DataReceived event is raised on a secondary thread when data is received from the SerialPort object

所以我认为您的代码示例不会以死锁告终。

但是,标题中你问题的答案:

Can a blocked thread fire events?

没有

回答标题中的问题:不能。被阻塞的线程不能引发事件。 但是,如果另一个线程负责引发事件,它应该按预期工作。

为了说明这一点,这里有一个例子:

internal class Program
{
    private static readonly AutoResetEvent RxDataReady = new AutoResetEvent(false);

    private static event EventHandler ev;

    public static void GetSomeDataFromSerialPort()
    {
        RxDataReady.WaitOne();

        // Process data
    }

    private static void Main()
    {
        ev += ReadDataEventHandler;
        Task.Run(
            async () =>
                {
                    await Task.Delay(5000);
                    ev(null, EventArgs.Empty);
                });
        GetSomeDataFromSerialPort();

        Console.WriteLine("Done.");
        Console.ReadLine();
    }

    private static void ReadDataEventHandler(object sender, EventArgs eventArgs)
    {
        // Prepare data
        RxDataReady.Set();
    }
}

这段代码所做的只是启动一个等待 5 秒的新线程,然后引发一个事件。 如果您尝试 运行 执行此操作,您会在 5 秒后看到 "Done." 显示在控制台中。

如果您要在同一线程上引发事件:

 private static void Main()
    {
        ev += ReadDataEventHandler;
        GetSomeDataFromSerialPort();
        ev(null, EventArgs.Empty);

        Console.WriteLine("Done.");
        Console.ReadLine();
    }

那么事件将永远不会被引发,并且执行将永远不会继续超过 RxDataReady.WaitOne()

另一种方法是 运行 GetSomeDataFromSerialPort() 在不同的线程上。