Может ли заблокированный поток инициировать события?

У меня есть программа, которая порождает поток, управляющий последовательной связью. Пока он ожидает ответа от последовательного порта, я блокирую поток с помощью 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() в другой теме.

Другие вопросы по тегам