title: How to make two background workers use the same serial port?
body: <p>I have an application that communicates with a microcontroller via serial port and I need to check the controller's status periodically in a Background Worker, and also allow the user to interact with the controller asynchronously (via user interface), by sending commands and receiving responses (also in a Background Worker).</p>
  
  <p>This is my Serial Communication class:</p>
  
  <pre><code>using System;
  using System.IO.Ports;
  using System.Timers;
  
  namespace GUI_WPF
  {
  static class SerialCommunication
  {
      static SerialPort serialPort = new SerialPort();
      static int readWriteTimeout = 2000; // [ms]
      static string endOfString = "" + char.MinValue;
  
      static object _commandLock = new object();
  
      public static void SerialPortInit(string portName)
      {
          if (serialPort.IsOpen == true)
          {
              serialPort.Close();
          }
  
          serialPort.PortName = portName;
          serialPort.BaudRate = 115200;
          serialPort.Parity = Parity.None;
          serialPort.DataBits = 8;
          serialPort.StopBits = StopBits.One;
          serialPort.Handshake = Handshake.None;
  
          // Set the read/write timeouts [ms]
          serialPort.ReadTimeout = readWriteTimeout;
          serialPort.WriteTimeout = readWriteTimeout;
  
          serialPort.Open();
      }
  
      public static string SerialRead()
      {
          try
          {
              serialPort.DiscardInBuffer();
              return serialPort.ReadTo(endOfString);
          }
          catch (Exception ex)
          {
              throw new Exception("SerialCommunication.SerialRead(): " + ex.Message);
          }
      }
  
      public static string SerialRead(int numberOfReads)
      {
          try
          { // The controller sends terminator char after each value transmitted, so using this method we can read multiple values
              serialPort.DiscardInBuffer();
              string response = "";
              for (int i = 0; i &lt; numberOfReads; i++)
              {
                  response += serialPort.ReadTo(endOfString) + " ";
              }
              return response;
          }
          catch (Exception ex)
          {
              throw new Exception("SerialCommunication.SerialRead(): " + ex.Message);
          }
      }
  
      public static void SerialWrite(string text)
      {
          try
          {
              serialPort.DiscardOutBuffer();
              serialPort.Write(text);
          }
          catch (Exception ex)
          {
              throw new Exception("SerialCommunication.SerialWrite(): " + ex.Message);
          }
      }
  
      public static string SerialWriteAndRead(string text)
      {
          lock (_commandLock) // If command is called from a thread while is executed on another thread, the lock forces the calling thread to wait
          {
              SerialWrite(text);
              return SerialRead();
          }
      }
  
      public static string SerialWriteAndRead(string text, int numberOfReads)
      {
          lock (_commandLock) // If command is called from a thread while is executed on another thread, the lock forces the calling thread to wait
          { // The controller sends terminator char after each value transmitted, so using this method we can read multiple values
              SerialWrite(text);
              return SerialRead(numberOfReads);
          }
      }
  
      public static string SerialRead(int numberOfReads, int timeoutMillisecods)
      {
          serialPort.ReadTimeout = timeoutMillisecods;
          string response = SerialRead(numberOfReads);
          serialPort.ReadTimeout = readWriteTimeout;
          return response;
      }
  
      public static string[] GetSerialPorts()
      {
          return SerialPort.GetPortNames();
      }
  
      public static void ClosePort()
      {
          try
          {
              if (serialPort.IsOpen == true)
              {
                  serialPort.Close();
              }
          }
          catch { }
      }
  }
  }
  </code></pre>
  
  <p>In a scenario, the monitor interrogates the controller every 2 seconds. Sometimes (most of the times) when the user issues from the GUI a command which waits for a response, the following exception appears: The I/O operation has been aborted because of either a thread exit or an app request.</p>
  
  <p><strong>Why does the "lock()" method not work? How can it be done?</strong></p>