title: Exception of An asynchronous read operation is already in progress on the StandardOutput stream
body: <p>I'm trying to use C# to control a command line application background, which can be downloaded here: <a href="http://www.ti.com/litv/zip/spmc015b" rel="nofollow">http://www.ti.com/litv/zip/spmc015b</a></p>
  
  <p>This is an app for motor voltage control, when I enter the app, like "b.exe -c 1", the console seems a kind of blocking model. Every command in this app begins with "#" symbol. See pics here:</p>
  
  <p><a href="http://i46.tinypic.com/zx5edv.jpg" rel="nofollow">http://i46.tinypic.com/zx5edv.jpg</a></p>
  
  <p>What I'm trying to do is, use StandardInput.WriteLine("stat vout"); to measure the voltage. This will send a "stat vout" command to the console background and ideally return a voltage value. In this pic, it return some help hints. Duing all this time, it still in the blocking mode.</p>
  
  <p>I want to get the return message with StandardOutput.ReadLine(); but failed. If ReadToEnd() then my program is freezed because this app never return to standard console, which is blocking.</p>
  
  <p>When I tried BeginOutputReadLine(); OutputDataReceived event can truly obtain the message return from the console, like in the pics of "stat [vout|vbus|fault". But it limited in my single thread program.</p>
  
  <p>My current situation is that, I use System.Timers.Timers in WinForms and every second will send a  "stat vout2" command to read the voltage, and hopefully get the return value.</p>
  
  <p>However, the System.Timers.Timers is asynchronous, so when I called BeginOutputReadLine() in this Timers thread, it prompted "An async read operation has already been started on the stream." In the meantime, as I've demonstrated above, I cannot use synchronous methods like ReadLine() to get the value.</p>
  
  <p>So what should I do now? I truly need to run this command line app in multi-threading mode.</p>
  
  <p>Thanks so much and wish everybody has a nice weekend.</p>
  
  <p>--UPDATE on Apr 28 19:18 CST
  Here is the relevant source code:</p>
  
  <p>One of the WinFroms button will Start() the SystemClock Class, then Timing.Measuring() is executed every second. The TimingController Class will call GetVoltage() and GetCurrent() at the same time during one second according to the SystemClock, to measure the voltage and current.</p>
  
  <p>In the Measuring Class, StandardInput.WriteLine("stat vout2"); to get the voltage from the console app, and StandardInput.WriteLine("stat cur"); to get the current. Both of them use BeginOutputReadLine() to get result since StandardOutput didn't work.</p>
  
  <p>I use a isOutputObtained flag to indicating if data returned. Every time the reading is finished, I did call CancelOutputRead(); to cancel asynchronous read.</p>
  
  <p>But it still give me the error exception of "An asynchronous read operation is already in progress on the StandardOutput stream"</p>
  
  <pre><code>public class SystemClock
  {
      TimingController Timing = new TimingController();
      private Timer TimerSystemClock;
  
      public SystemClock()
      {
          TimerSystemClock = new Timer();
          TimerSystemClock.Interval = 1000;
          TimerSystemClock.AutoReset = true;
          TimerSystemClock.Elapsed += new ElapsedEventHandler(TimerSystemClock_Elapsed);
          TimerSystemClock.Enabled = false;
          Timing.ClockInstance = this;
      }
  
      public void Start()
      {
          TimerSystemClock.Enabled = true;
      }
  
      void TimerSystemClock_Elapsed(object sender, ElapsedEventArgs e)
      {
          Timing.Measuring();
      }
  }
  
  public class TimingController
  {
      // Get singleton of Measurement Class
      Measurement Measure = Measurement.GetInstance();       
  
      public SystemClock ClockInstance
      {
          get { return Clock; }
          set { Clock = value; }
      }
  
      private void Measuring()
      {
          CurrentVoltage = Measure.GetVoltage();
          CurrentCurrent = Measure.GetCurrent();
      }
  }
  
  public sealed class Measurement
  {
      // Singleton
      public static readonly Measurement instance = new Measurement();
      public static Measurement GetInstance()
      {
          return instance;
      }
  
      private Process ProcMeasuring = new Process();
      double measureValue
      bool isOutputObtained;
  
      private Measurement()
      {
          ProcMeasuring.StartInfo.FileName = "b.exe";
          ProcMeasuring.StartInfo.Arguments = "-c 1";
          ProcMeasuring.StartInfo.WorkingDirectory = Directory.GetCurrentDirectory();
          ProcMeasuring.StartInfo.UseShellExecute = false;
          ProcMeasuring.StartInfo.RedirectStandardInput = true;
          ProcMeasuring.StartInfo.RedirectStandardOutput = true;
          ProcMeasuring.StartInfo.RedirectStandardError = true;
          ProcMeasuring.StartInfo.CreateNoWindow = true;
          ProcMeasuring.OutputDataReceived += new DataReceivedEventHandler(MeasurementOutputHandler);
      }
  
      public double GetVoltage(Machine machine)
      {
          isOutputObtained = false;
  
          ProcMeasuring.StandardInput.WriteLine("stat vout2");
          ProcMeasuring.BeginOutputReadLine();
  
          while (!isOutputObtained)
          {
              isOutputObtained = true;
          }
  
          return measureValue;
      }
  
      public double GetCurrent(Machine machine)
      {
          isOutputObtained = false;
  
          ProcMeasuring.StandardInput.WriteLine("stat cur");
          ProcMeasuring.BeginOutputReadLine();
  
          while (!isOutputObtained)
          {
              isOutputObtained = true;
          }
  
          return measureValue;
      }
  
      private void MeasurementOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
      {
          if (!String.IsNullOrEmpty(outLine.Data) &amp;&amp; (outLine.Data != "# "))
          {                
              measureCurrentValue = Convert.ToDouble(outLine.Data);
              isOutputObtained = true;
  
              ProcMeasuring.CancelOutputRead();
          }
      }
  }
  </code></pre>