Can someone point me to a working example that uses the .net 4.5 Async API (async, wait, task <>, ReadAsync, etc.) for serial communication?
I tried to adapt an existing event-based serial sample and I get all kinds of terrible behavior - "port in use by other applications" errors, VS2013 debugger that throws exceptions and blocking - which usually require a computer reboot to recover from.
change
I wrote my own sample from scratch. This is a simple Winforms project that is written to the output window. Three buttons in the form: "Open Port", "Close Port" and "Read Data". The ReadDataAsync method calls SerialPort.BaseStream.ReadAsync.
At the moment, it will read data from the port, but I am having problems that make it reliable.
For example, if I disconnect the serial cable, open the port and double-click Read Data, I will get a System.IO.IOException (which I expect), but the application stops responding.
Worse, when I try to stop my program, VS2013 launches the Stop Stop Debugging In Process dialog, which never ends, and I cannot even kill VS from the task manager. You have to restart your computer every time this happens.
Not good.
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();
}
}
}