0

シリアルポートから非常に高速で継続的にデータを取得しようとしています。ボーレートは230400です。データ、タイムスタンプ、およびファイルを印刷すると、1桁に落ちて、その200ミリ秒で何も読み取らないBytesToRead場合は常に、200ミリ秒の遅延が発生することに気付きました。遅延後、約3000に戻り、このプロセスが何度も繰り返されます。基本的に、私は継続的にデータを取得していません。BytesToReadreadLine()BytesToRead

バッファに蓄積される速度データよりも速く読み取っていると思ったので、readBufferのサイズを変更して、このスレッドを1ミリ秒間スリープさせ、バッファが読み取っている速度を維持できるようにしました。それらのどれも機能しませんでした。まだいくつかの遅れがあります。

どんな考えでも大歓迎です。

 private void dostuff()//The thread I created after the port is opened
    {
        var startTime = DateTime.Now;
        var stopwatch = Stopwatch.StartNew();
        while (serialPortEncoder.IsOpen)
        {
            if (serialPortEncoder.BytesToRead > 210)
            {
                try
                {
                    var line = serialPortEncoder.ReadLine();
                    var timestamp = (startTime + stopwatch.Elapsed);
                    var lineString = string.Format("{0}  ----{1}",
                                    line,
                                    timestamp.ToString("HH:mm:ss:fff") + " "+serialPortEncoder.BytesToRead+"\r\n");

                    richTextBoxEncoderData.BeginInvoke(new MethodInvoker(delegate()
                    {
                        richTextBoxEncoderData.Text = line;//update UI                           
                    }));                                     
                }
                catch (Exception ex) { MessageBox.Show(ex.ToString()); }


            }}
4

3 に答える 3

3

210バイトごとに改行がない限り、ReadLine()関数はおそらくタイムアウトして何も返さないでしょう。ReadLine()は、改行値が検出されるまで入力バッファーを読み取り、それ以前のデータを返します。http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.readline.aspx

港を越えてどのような情報が届いていますか?特定のサイズのバッファを読み取りたい場合は、このReadメソッドを使用してください。改行ができるまで読み取る必要がある場合は、ReadLine()を使用して、文字列が返されるかどうかを頻繁に確認してください。

于 2013-01-14T17:38:46.750 に答える
2

あなたのコードはかなり根本的に欠陥があり、「ホットウェイトループ」のバグに悩まされています。シリアルポートに十分なデータがない場合、ループは100%コアを書き込みます。これにより、Windowsは、クォンタムを焼き付けた後、しばらくの間スレッドを犬小屋に置き、他のスレッドを実行する機会を与えます。その犬小屋に200ミリ秒いるのは少し長いですが、確かに珍しいことではありません。

これは別の方法で行う必要があります。シリアルポートから実際に利用可能なデータがあるときに、Windowsにウェイクアップする機会を与える必要があります。スケジュールする次のスレッドを探すときに、I/Oが完了したスレッドを優先します。これは非常に簡単です。BytesToReadテストを削除するだけです。ReadLine()呼び出しは、NewLineが受信されるまで戻らないブロッキング呼び出しです。これで、スレッドは0%近くのCPUサイクルを消費します。

マシンの負荷が高い場合やガベージコレクターが実行されている場合でも、任意の時間が失われます。いいえ、それはエンコーダーを確実に読み取り、フィードバックループを閉じるには十分ではありません。これを確実に行うには、予測可能なリアルタイム動作を備えたマイクロコントローラーが必要です。産業用電子機器のサプライヤーからすぐに入手できます。

于 2013-01-14T17:46:17.767 に答える
0

ウェブ上で何度か調査した結果、遅延の原因を見つけました。デバイスマネージャー--->ポート---->詳細---->レイテンシを1msに変更すると、問題が解決します。これで、バッファがゼロに低下するたびに、通常に戻るのに最大2ミリ秒しか必要ありません。現在、別のスレッドを使用してデータをポーリングしています。それは非常にうまく機能します。

しかし、ハンス・パッサントが言ったように、私はそれを設計するためのより良い方法を見つけようとしています。

于 2013-01-15T02:09:05.307 に答える