title: Sample serial port comms code using Async API in .net 4.5?
body: <p>Can anyone point me to a working example that uses the .net 4.5 Async API (async, await, task&lt;>, ReadAsync, etc) to do serial communications?</p>
  
  <p>I've tried to adapt an existing event driven serial sample, and am getting all kinds of horrible behavior - "port in use by other application" errors, VS2013 debugger throwing exceptions and locking up - which usually require a PC reboot to recover from.</p>
  
  <p><strong>edit</strong></p>
  
  <p>I've written my own sample from scratch.  It's a simple Winforms project that writes to the Output window.  Three buttons on the form - Open Port, Close Port, and Read Data.  The ReadDataAsync method calls SerialPort.BaseStream.ReadAsync.</p>
  
  <p>As of now, it will read data from the port, but I'm running into problems making it robust. </p>
  
  <p>For example, if I unplug the serial cable, open the port, and click Read Data twice, I will get an System.IO.IOException (which I kind of expect), but my app stops responding.</p>
  
  <p>Worse, when I try to stop my program, VS2013 throws up a "Stop Debugging in Progress" dialog, which never completes, and I can't even kill VS from Task Manager.  Have to reboot my PC every time this happens.</p>
  
  <p>Not good.</p>
  
  <pre><code>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&lt;int&gt; 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();
          }
  
      }
  }
  </code></pre>