Я просто предисловие к этому, сказав, что я начал использовать Async сегодня, поэтому у меня очень ограниченное понимание того, что я делаю.Непрерывно читает из последовательного порта асинхронно
Раньше я использовал потоки для чтения данных из последовательного порта, обрабатывал эти данные в данных для записи, а затем записывал их. У меня было 1 поток данных чтения и размещение его в буфере, другой поток обработки данных из буфера и окончательный поток, пишущий его. Таким образом, если бы я нажал кнопку, я мог бы отправить дополнительные данные.
Теперь я просто пытаюсь узнать и убедиться, что все делаю правильно, поэтому я пытаюсь прочитать данные из последовательного порта и добавить эти данные в многострочное текстовое поле. Вот код:
Подключения к последовательному порту, в случае успеха, звоните UpdateMessageBox
, который асинхронный:
private void serialConnectClick(object sender, EventArgs e)
{
if (!_serialConnected)
{
_serialConnected = SerialConnect(portCombo.Text, int.Parse(baudCombo.Text));
if (!_serialConnected)
{
portCombo.SelectedIndex = 0;
messageTextBox.Text += "Failed to connect.\r\n";
return;
}
serialConnectBtn.Text = "Disconnect";
serialStatusLabel.Text = "Serial: Connected";
serialStatusLabel.ForeColor = Color.Blue;
messageTextBox.Text += "Connected\r\n";
VDIportCombo.Enabled = false;
soundSuccess.Play();
UpdateMessageBox(); // this is an async function
}
}
Это постоянно вызывает ReadLineAsync
и добавляет результат в текстовое поле:
public async Task UpdateMessageBox()
{
messageTextBox.Text += "Reading data from serial.";
while (_serialConnected)
{
string message = await SerialReadLineAsync(serial);
messageTextBox.Text += message;
}
}
И это делает ReadAsync
на SerialPort.BaseStream
и возвращает только данные, когда мы получаем полную строку (обозначается символом новой строки):
async Task<string> SerialReadLineAsync(SerialPort serialPort)
{
byte[] buffer = new byte[1];
string result = string.Empty;
Debug.WriteLine("Let's start reading.");
while (true)
{
await serialPort.BaseStream.ReadAsync(buffer, 0, 1);
result += serialPort.Encoding.GetString(buffer);
if (result.EndsWith(serialPort.NewLine))
{
result = result.Substring(0, result.Length - serialPort.NewLine.Length);
result.TrimEnd('\r','\n');
Debug.Write(string.Format("Data: {0}", result));
result += "\r\n";
return result;
}
}
}
Я все правильно делаю? Могу ли я вызвать метод асинхронизации из потока пользовательского интерфейса? Визуальные студии говорят мне, что мне нужно использовать использовать, но это просто означает, что.
Я хочу, чтобы другой код работал в потоке пользовательского интерфейса, пока он постоянно читает, поэтому я не хочу await
UpdateMessageBox
. Если бы это был поток, я бы просто хотел, чтобы прочитанный поток работал в фоновом режиме, и я бы просто сделал myReadThread.Start()
, есть ли что-то подобное для async?
EDIT: Чтобы уточнить, этот код действительно работает, но я хочу знать, является ли это «правильным» способом делать то, что я делаю.
Ах, не знал, что смогу сделать эту функцию асинхронной! Есть ли способ, которым мне не нужно «ждать» «UpdateMessageBox»? Когда я включаю ключевое слово 'await', я получаю' IOExceptions', когда я нажимаю кнопку второй раз (который в настоящее время запрограммирован на закрытие последовательного порта) –
Для любого в будущем вы можете! Просто добавьте '.ConfigureAwait (false);' поэтому, это должно быть 'UpdateMessageBox(). ConfigureAwait (false);' –
Вы уверены, что можете. Просто будьте осторожны с использованием 'ConfigureAwait (false)' во время UI-метода, иначе оператор, следующий за ним, потенциально может выполняться в другом потоке. В противном случае, если вы не заботитесь о том, какой поток использовать, используйте 'ConfigureAwait (false)'. [Расскажите подробнее] (https://msdn.microsoft.com/en-us/magazine/jj991977.aspx) – MickyD