任何人都可以指向一個使用.net 4.5異步API(異步,等待,任務<>,ReadAsync等)進行串行通信的工作示例嗎?我試圖改編現有的事件驅動的串行示例,並獲取各種可怕的行爲 - 「其他應用程序使用的端口」錯誤,VS2013調試器拋出異常並鎖定 - 通常需要PC重新啓動從中恢復。使用.net 4.5中的Async API的串口通信代碼示例?
編輯
我已經寫了從無到有我自己的樣品。這是一個寫入輸出窗口的簡單的Winforms項目。表單上的三個按鈕 - 打開端口,關閉端口和讀取數據。 ReadDataAsync方法調用SerialPort.BaseStream.ReadAsync。
截至目前,它會從端口讀取數據,但我遇到了問題,使其強大。例如,如果我拔掉串行電纜,打開端口,然後單擊讀取數據兩次,我將得到一個System.IO.IOException(我期待的),但是我的應用程序停止響應。更糟糕的是,當我嘗試停止我的程序時,VS2013拋出一個「停止調試進行中」對話框,它永遠不會完成,我甚至無法從任務管理器中殺死VS.每次發生這種情況時都必須重啓我的電腦。
不好。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private SerialPort _serialPort;
public Form1()
{
InitializeComponent();
}
private void openPortbutton_Click(object sender, EventArgs e)
{
try
{
if (_serialPort == null)
_serialPort = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
if (!_serialPort.IsOpen)
_serialPort.Open();
Console.Write("Open...");
}
catch(Exception ex)
{
ClosePort();
MessageBox.Show(ex.ToString());
}
}
private void closePortButton_Click(object sender, EventArgs e)
{
ClosePort();
}
private async void ReadDataButton_Click(object sender, EventArgs e)
{
try
{
await ReadDataAsync();
}
catch (Exception ex)
{
ClosePort();
MessageBox.Show(ex.ToString(), "ReadDataButton_Click");
}
}
private async Task ReadDataAsync()
{
byte[] buffer = new byte[4096];
Task<int> readStringTask = _serialPort.BaseStream.ReadAsync(buffer, 0, 100);
if (!readStringTask.IsCompleted)
Console.WriteLine("Waiting...");
int bytesRead = await readStringTask;
string data = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine(data);
}
private void ClosePort()
{
if (_serialPort == null) return;
if (_serialPort.IsOpen)
_serialPort.Close();
_serialPort.Dispose();
_serialPort = null;
Console.WriteLine("Close");
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
ClosePort();
}
}
}
SerialPort沒有異步方法,因爲它本質上是異步性質的,它使用線程來處理通信,因此只需使用它的方法和事件就足夠了。發佈你的代碼來檢查它,看看有什麼不對。還添加錯誤。 – Gusman
其他SO帖子暗示我可以使用像SerialPort.BaseStream.ReadAsync等東西,我打電話給這個方法。你是說這不起作用嗎? –
嗯,從來沒有使用SerialPort的底層流,但我懷疑它不會正常工作(也許我錯了),我已經使用了多年的SerialPort並使用Write和Read函數和DataReceived事件應該已經足夠並且已經異步。 – Gusman