首先声明一下,我今天刚开始尝试使用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;
}
}
这里使用 SerialPort.BaseStream
上的 ReadAsync
方法,仅在接收到完整的一行数据(以换行符表示)时才返回数据:
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;
}
}
}
我是否做得正确?我能在UI线程中调用异步方法吗?Visual Studios告诉我我应该使用await,但它只是建议。
我想让其他代码在UI线程上运行,同时也要持续地读取数据,所以我不想await
UpdateMessageBox
函数。如果这是一个线程,我只希望读取线程在后台运行,我只需执行 myReadThread.Start()
,那么在异步情况下是否有类似的方法呢?编辑:只是为了澄清,这段代码确实可以工作,但我想知道这样做是否是“正确”的方式。
await
UpdateMessageBox
?当我包含await
关键字时,第二次按下按钮(目前编程为关闭串口)时会出现IOexceptions
。 - Xander Luciano.ConfigureAwait(false);
,因此应该是UpdateMessageBox().ConfigureAwait(false);
。 - Xander LucianoConfigureAwait(false)
,否则紧随其后的语句可能会在不同的线程上执行。否则,如果您不关心使用哪个线程,请使用ConfigureAwait(false)
。了解更多 - user585968