5

ここでダウンロードできるコマンド ライン アプリケーションのバックグラウンドを制御するために C# を使用しようとしています: http://www.ti.com/litv/zip/spmc015b

これはモーター電圧制御用のアプリです。「b.exe -c 1」のようにアプリに入ると、コンソールは一種のブロック モデルのように見えます。このアプリのすべてのコマンドは「#」記号で始まります。ここで写真を見てください:

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

私がやろうとしているのは、StandardInput.WriteLine("stat vout"); を使用することです。電圧を測定します。これにより、「stat vout」コマンドがコンソール バックグラウンドに送信され、理想的には電圧値が返されます。この写真では、いくつかのヘルプ ヒントが返されます。この間ずっと、まだブロッキングモードです。

StandardOutput.ReadLine(); で戻りメッセージを取得したい しかし失敗しました。ReadToEnd() の場合、このアプリはブロックしている標準コンソールに戻らないため、プログラムがフリーズします。

私が試したとき BeginOutputReadLine(); OutputDataReceived イベントは、「stat [vout|vbus|fault」の写真のように、コンソールから返されるメッセージを真に取得できます。しかし、それは私のシングルスレッドプログラムでは制限されていました.

私の現在の状況は、WinForms で System.Timers.Timers を使用し、毎秒「stat vout2」コマンドを送信して電圧を読み取り、できれば戻り値を取得することです。

ただし、System.Timers.Timers は非同期であるため、この Timers スレッドで BeginOutputReadLine() を呼び出すと、「ストリームで非同期読み取り操作が既に開始されています」というメッセージが表示されました。それまでの間、上で説明したように、ReadLine() のような同期メソッドを使用して値を取得することはできません。

それで、私は今何をすべきですか?このコマンド ライン アプリをマルチスレッド モードで実行する必要があります。

どうもありがとうございました。皆さんが良い週末を過ごせますように。

--4 月 28 日 19:18 CST の更新: 関連するソース コードは次のとおりです。

WinFroms ボタンの 1 つは SystemClock クラスを Start() し、Timing.Measuring() が毎秒実行されます。TimingController クラスは、電圧と電流を測定するために、SystemClock に従って 1 秒間に GetVoltage() と GetCurrent() を同時に呼び出します。

測定クラスでは、StandardInput.WriteLine("stat vout2"); コンソールアプリから電圧を取得し、StandardInput.WriteLine("stat cur"); 電流を取得します。StandardOutput が機能しなかったため、どちらも BeginOutputReadLine() を使用して結果を取得します。

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();
        }
    }
}
4

1 に答える 1

0

あなたには2つの選択肢があると思います。

前のサンプルに時間がかかりすぎたためにサンプルを見逃しても問題ない場合は、既にサンプリングしていることを示すフラグを設定します。

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;
    }  
} 

間隔を空けても問題ない場合は、既存のプロセスを再利用するのではなく、呼び出しごとに新しいプロセス オブジェクトを作成してみてください。ただし、コマンドの完了に時間がかかる場合は、多くの子が作成される可能性があります。

于 2012-05-04T14:11:08.413 に答える