阻塞的线程可以触发事件吗?
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()
在不同的线程上。
我有一个程序生成一个控制串行通信的线程。当它等待串行端口上的响应时,我用 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()
在不同的线程上。