title: Processing intermittent IO jobs with TPL and/or BackgroundWorker
body: <p>I have a C# application that interacts with a few serial and USB devices. I am trying to find a nice way to command these devices in a parallel fashion so that many can be controlled at once. I will initiate commands to the device via user input and also scripted commands.</p>
  
  <p>I am currently trying to figure out a clean way to "collect" and run commands in parallel to my UI thread. I have multiple forms, one for each device, each have a few controls that can issue commands.</p>
  
  <p>The way I currently see it a user will click a button which will fire an event in the form. Another class lets call it <code>CommandManager</code> will hook into all of these events; each event passes the necessary information to form a command to send to a device.</p>
  
  <p>When the event is handled by the <code>CommandManager</code> it forms the command and adds it to a <code>BlockingCollection&lt;Command&gt;</code> in a subclassed <code>BackgroundWorker</code> named <code>DeviceCommandWorker</code> which was started when the application opened. All it does is loop over a block of code containing a <code>Task.Factory.StartNew()</code> call. </p>
  
  <p>In the <code>StartNew</code> block <code>Take</code> is called on the <code>BlockingCollection</code> waiting for a command to be input. Once a command is in the collection the <code>Take</code> returns and the <code>Task</code> goes off on its merry way. The <code>BackgroundWorker</code> loops back around and repeats the process until it is cancelled. </p>
  
  <pre><code>// Event handler running on the UI Thread
  public void ProcessCommand(DeviceCommand command)
  {
      // I assume I cannot add to Commands (BlockingCollection) from here?
      DeviceCommandWorker.Instance.Commands.Add(command);
  }
  
  // ....
  // BackgroundWorker started upon Application startup
  // ...
  
  public class DeviceCommandWorker : BackgroundWorker
  {
      public static DeviceCommandWorker Instance { get { return lazyInstance.Value; } }
      private static readonly Lazy&lt;DeviceCommandWorker&gt; lazyInstance = new Lazy&lt;DeviceCommandWorker&gt;(() =&gt; new DeviceCommandWorker());
  
      public BlockingCollection&lt;DeviceCommand&gt; Commands { get; set; } 
  
      private DeviceCommandWorker()
      {
          WorkerSupportsCancellation = true;
          Commands = new BlockingCollection&lt;DeviceCommand&gt;();
      }
  
      protected override void OnDoWork(DoWorkEventArgs e)
      {
          while (!CancellationPending)
          {
              var commandTask = Task.Factory.StartNew(() =&gt;
              {
                  // If the BackGroundWorker is cancelled, how to esacpe this blocking call?
                  DeviceCommand command = commandQueue.Take(); 
  
                  DeviceCommandResult result;
                  command.Process(out result);
  
                  if(result == DeviceCommandResult.Error)
                      ; // How would I inform the UI of this result?
              });
          }
          e.Cancel = true;
      }
  }
  </code></pre>
  
  <p>My questions are stated in the code above but I will reiterate them. </p>
  
  <p>My first issue is that I do not think I can add to the <code>BlockingCollection</code> from outside the running <code>BackGroundWorker</code>? (From reading about the TPL, shouldn't there be a sync object I can lock on when adding?)</p>
  
  <p>Assuming that I can add to the collection, is there no way to escape the <code>Take</code> method when it is blocking, specifically if the <code>BackgroundWorker</code> was cancelled wouldn't it just be blocked forever? (Possibly before  cancellation I could send a "custom command" that simply creates a task that does nothing, I would then be able to exit the while loop)</p>
  
  <p>Finally, how would I report either success or errors in command execution back to the UI thread? I have seen this <a href="https://stackoverflow.com/a/4331287/2985796">SO answer</a>, is that the right direction to head in?</p>