Я потратил некоторое время на поиск ответа на этот вопрос и нашел много полезной информации в других темах. Я считаю, что написал код так, чтобы он работал, но я не доволен результатом.
Я разработал аппаратное обеспечение, с которым общаюсь через С#. Аппаратное обеспечение подключается через USB и запускает процедуры инициализации после перечисления с ОС. В этот момент он просто ждет, пока программа C# начнет отправлять команды. В моем коде C# пользователь должен нажать кнопку «Подключить», которая отправляет команду и требуемую полезную нагрузку, чтобы оборудование знало, что оно должно продолжать работать. Затем аппаратное обеспечение отправляет команду обратно в виде ACK. Проблема в том, что моя программа на С# должна ждать получения ACK, но графический интерфейс полностью зависает до тех пор, пока аппаратное обеспечение не ответит, поскольку я не знаю, как разделить его на другой поток, который может свободно блокироваться. Если оборудование отвечает немедленно, то оно работает нормально, но если оно не может подключиться, то программа остается замороженной на неопределенный срок.
С учетом сказанного я знаю, что должно произойти несколько вещей, но я не уверен, как их реализовать. Прежде всего, я не думаю, что сидеть в цикле, ожидая логического значения, - это правильный путь, но использование AutoResetEvent на самом деле не кажется намного лучше. Должен быть лучший способ с использованием таймеров, большего количества потоков или чего-то подобного.
Я использую событие DataReceived с объектом serialPort следующим образом:
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
byte cmd = (byte)serialPort1.ReadByte();
if (cmd == (byte)Commands.USB_UART_CMD_MCU_CONNECT)
MCU_Connect_Received.Set();
}
В функции buttonClick ("основной" поток) программа останавливается, ожидая ACK:
//Send the command to signal a connection
Send_Connection_Packet((byte)Commands.USB_UART_CMD_PC_CONNECT);
textBox1.AppendText("-I- Attempting to contact hardware...");
MCU_Connect_Received.WaitOne();
textBox1.AppendText("Success!" + Environment.NewLine);
В идеале я хотел бы знать, истек ли тайм-аут, чтобы я мог напечатать «Ошибка!» вместо «Успех!». Отсутствие тайм-аута также означает, что он будет оставаться там вечно, как я уже упоминал выше, пока я не убью процесс. Возможно, он не найдет никакого оборудования, но если найдет, то должен ответить через ‹ 1 секунды, так что тайм-аута в 2 секунды будет более чем достаточно. Я попытался использовать Thread.Sleep, но это также заморозило графический интерфейс.