Может ли заблокированный поток инициировать события?
У меня есть программа, которая порождает поток, управляющий последовательной связью. Пока он ожидает ответа от последовательного порта, я блокирую поток с помощью 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 ответа
Замечания от MSDN SerialPort.DataReceived
Событие DataReceived возникает во вторичном потоке при получении данных от объекта SerialPort
Так что я не думаю, что ваш пример кода окажется в тупике.
Тем не менее, ответ на ваш вопрос в заголовке:
Может ли заблокированный поток инициировать события?
Нет.
Чтобы ответить на вопрос в заголовке: Нет. Заблокированная тема не может вызвать событие. Однако если за создание события отвечает другой поток, он должен работать как положено.
Чтобы проиллюстрировать это, вот пример:
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()
в другой теме.