1

私は ASM と C for PIC の経験があり、コーディングにはかなり慣れていません。私はまだC#で高レベルのプログラミングを学んでいます。

質問

C# でシリアル ポートのデータ受信および処理プログラムを作成しました。データが失われるのを避け、データがいつ来るかを知るために、DataReceivedイベントを設定し、読み取るバイトがなくなるまで処理メソッドにループします。

これを試みたところ、ループが際限なく続き、データを連続して受信すると、プログラムが他のタスク (取得したデータの処理など) からブロックされました。

C# でのスレッド化について読み、SerialPort.Bytes2Readプロパティを常にチェックするスレッドを作成して、利用可能なデータをいつ取得するかを認識できるようにしました。

新しいデータがまだ読み取られている間にデータを処理できる 2 番目のスレッドを作成しました。バイトが読み取られ、ReadSerial() にさらに読み取るバイトがあり、タイムアウト (シリアルから新しいバイトが読み取られるたびに再起動される) の場合、それらは引き続き処理され、DataProcessing() という名前のメソッドを介してフレームが組み立てられます。 ReadSerial() によって埋められる同じ変数。

これにより望ましい結果が得られましたが、私のソリューション ( ReadSerial()DataProcessing()スレッドの両方が有効) では、CPU 使用率が 100% まで急上昇したことに気付きました!

このような高い CPU 使用率を引き起こさずに、この問題にどのように対処しますか?

public static void ReadSerial() //Method that handles Serial Reception
{
    while (KeepAlive) // Bool variable used to keep alive the thread. Turned to false
    {                 // when the program ends.
        if (Port.BytesToRead != 0)
        {
            for (int i = 0; i < 5000; i++) 
            {

             /* I Don't know any other way to 
                implement a timeout to wait for 
                additional characters so i took what 
                i knew from PIC Serial Data Handling. */

                if (Port.BytesToRead != 0)
                {
                    RxList.Add(Convert.ToByte(Port.ReadByte()));
                    i = 0;

                    if (RxList.Count > 20) // In case the method is stuck still reading
                        BufferReady = true; // signal the Data Processing thread to 
                 }                          // work with that chunk of data.

                 BufferReady = true; // signals the DataProcessing Method to work      
            }                        // with the current data in RxList.
        }         
    }    
}
4

1 に答える 1

0

「DataReceived」と「ループ」で何を意味しているのか完全には理解できません。また、シリアル ポートやその他のインターフェイスにも多く取り組んでいます。私のアプリケーションでは、DataReceived イベントにアタッチし、読み取るバイト数に基づいて読み取りを行っていますが、そこでループを使用していません。

int bytesToRead = this._port.BytesToRead;
var data = new byte[bytesToRead];
this._port.BaseStream.Read(data , 0, bytesToRead);

ループを使用してバイトを読み取る場合は、次のようなものをお勧めします。

  System.Threading.Thread.Sleep(...);

そうしないと、バイトの読み取りに使用しているスレッドが常にビジー状態になります。これにより、他のスレッドを処理できないか、CPU が 100% になるという事実につながります。

ただし、DataReceived イベントを使用している場合は、データのポーリングにループを使用する必要はないと思います。私の理解が正しくない場合、またはさらに情報が必要な場合は、お問い合わせください。

于 2013-07-24T23:34:42.827 に答える