5

Я пытаюсь использовать C# для управления фоном приложения командной строки, которую можно скачать здесь: http://www.ti.com/litv/zip/spmc015bИсключения асинхронной операции чтения уже идут на потоке StandardOutput

Это приложение для напряжения двигателя когда я вхожу в приложение, например «b.exe -c 1», консоль кажется своего рода блокирующей моделью. Каждая команда в этом приложении начинается с символа «#». Смотрите фотографии здесь:

http://i46.tinypic.com/zx5edv.jpg

То, что я пытаюсь сделать, это использовать StandardInput.WriteLine ("стат Vout"); для измерения напряжения. Это отправит команду «stat vout» на фон консоли и в идеале вернет значение напряжения. В этой статье он возвращает подсказки. Дуинг все это время, он все еще находится в режиме блокировки.

Я хочу получить обратное сообщение с помощью StandardOutput.ReadLine(); но не удалось. Если ReadToEnd(), то моя программа зависает, потому что это приложение никогда не возвращается к стандартной консоли, которая блокирует.

Когда я попробовал BeginOutputReadLine(); Событие OutputDataReceived может действительно получить возврат сообщения с консоли, как в pics of stat [vout | vbus | fault ». Но он ограничен в моей программе с одним потоком.

Моя нынешняя ситуация в том, что я использую System.Timers.Timers в WinForms и каждую секунду отправит команду «stat vout2» для чтения напряжения и, надеюсь, получит возвращаемое значение.

Однако System.Timers.Timers является асинхронным, поэтому, когда я вызывал BeginOutputReadLine() в этом потоке таймеров, он запрашивал: «В потоке уже запущена операция чтения async». Тем временем, как я показал выше, я не могу использовать синхронные методы, такие как ReadLine(), чтобы получить значение.

Итак, что мне теперь делать? Мне действительно нужно запустить это приложение командной строки в многопоточном режиме.

Большое спасибо и пожелайте всем приятного уик-энда.

--update 28 апреля 19:18 CST Вот соответствующий исходный код:

Один из WinFroms кнопка Пуск() для SystemClock класса, то Timing.Measuring() выполняется каждый второй. Класс TimingController вызовет GetVoltage() и GetCurrent() одновременно в течение одной секунды в соответствии с SystemClock для измерения напряжения и тока.

В измерительном классе, StandardInput.WriteLine ("stat vout2"); для получения напряжения из консольного приложения и StandardInput.WriteLine («stat cur»); для получения тока. Оба из них используют BeginOutputReadLine() для получения результата, поскольку StandardOutput не работает.

Я использую флаг isOutputObtained для указания возврата данных. Каждый раз, когда чтение заканчивается, я вызывал CancelOutputRead(); для отмены асинхронного чтения.

Но она по-прежнему дает мне исключение ошибок «Асинхронная операция чтения уже идут на потоке StandardOutput»

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) && (outLine.Data != "# ")) 
     {     
      measureCurrentValue = Convert.ToDouble(outLine.Data); 
      isOutputObtained = true; 

      ProcMeasuring.CancelOutputRead(); 
     } 
    } 
} 
+0

Проводка некоторых из приведенных выше кодов может помочь. –

+0

Мой код слишком длинный, я покажу его как новый ответ – Asker

+1

Нет, это не ответ. Поместите это в вопрос. –

ответ

0

Я думаю, что у вас есть два варианта.

Если вы пропустите образец, потому что предыдущий занимает слишком много времени, установите флаг, указывающий, что вы уже отбираете выборку.

public class TimingController 
{ 
    // Get singleton of Measurement Class 
    Measurement Measure = Measurement.GetInstance();   

    bool isMeasuring = false; 

    public SystemClock ClockInstance 
    { 
     get { return Clock; } 
     set { Clock = value; } 
    } 

    private void Measuring() 
    { 
     if(isMeasuring) return; 

     isMeasuring = true; 
     CurrentVoltage = Measure.GetVoltage(); 
     CurrentCurrent = Measure.GetCurrent(); 
     isMeasuring = false; 
    } 
} 

Если это не нормально, чтобы пропустить интервал, вы можете попробовать создать новый объект процесса для каждого вызова, вместо повторного использования существующего процесса. Это может создать много детей, хотя если команды занимают много времени.