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

时间:2016-12-13 08:36:29

标签: c# multithreading events autoresetevent

我有一个程序,它产生一个控制串行通信的线程。当它等待串口上的响应时,我用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();
}

非常感谢

2 个答案:

答案 0 :(得分:4)

来自MSDN SerialPort.DataReceived

的评论
  

从SerialPort对象接收数据时,在辅助线程上引发DataReceived事件

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

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

  

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

没有

答案 1 :(得分:1)

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

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

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秒后看到“完成”。显示在控制台中。

如果您要在同一个帖子上举起活动:

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

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

然后永远不会引发事件,执行将永远不会超过RxDataReady.WaitOne()

另一种方法是在另一个线程上运行GetSomeDataFromSerialPort()