2011-01-18 69 views
1

当社は、シリアルポートの通信のためのフォローのC#のコードを持っているの大多数蓄積:シリアルポートの通信が実行中のスレッド

   ProcCntrlSSPort = new SerialPort(portNumber, 115200, Parity.None, 8, StopBits.One); 

       ProcCntrlSSPort.Handshake = Handshake.None; 
       ProcCntrlSSPort.ReadTimeout = 10; 
       ProcCntrlSSPort.ReadBufferSize = 32768; 
       ProcCntrlSSPort.DataReceived += ProcCntrlSSPortDataReceived; 
       //ProcCntrlSSPort.DataReceived += new SerialDataReceivedEventHandler(ProcCntrlSSPortDataReceived); 
       ProcCntrlSSPort.ReceivedBytesThreshold = 1; 
       try 
       { 
        ProcCntrlSSPort.Open(); 
        ProcCntrlSSPort.DiscardInBuffer(); 
       } 

100msec毎に、当社のアプリケーションで受信したステータスメッセージがあります。私はSerialPortReceivedBytesThresholdバイト数を受け取ったときに、SerialPortによってイベントが発生することを理解しています。 ReceivedBytesThresholdには1を使用する必要があります。なぜなら、重要なデータの1つがそのバイトが利用可能なときは常に1バイトずつ送られるからです。

イベントがSerialPortによって発生し、受信者によって処理されると、そのイベントは破棄され、そのイベントに関連付けられたスレッドは次回の使用に使用できるようになります。実行中のスレッドの蓄積が大量にあってはいけません。

しかし、実行中のスレッドは、一晩後に20スレッドから400スレッド以上に連続的に増加することがわかりました。ちょうどステータスメッセージがアプリケーションに送信され、他のアクティビティは送信されません。 私はすべてのプロセスコードを無効にしていますので、蓄積されたスレッドは私たちのコードからではないと確信しています。つまり、テスト目的で受け取ったデータには何もしません。

ReceivedBytesThresholdをテスト用に128と増やしました。それは蓄積を遅くしますが、スレッド数は依然としてゆっくりと上がります。なぜ.netフレームワークがスレッドを正しく処理できないのですか?または私はそれを正しく使用しませんでしたか?

+1

Ummmm。スマート・アレッキーは聞こえませんが、.NET Frameworkではトレッドを正しく処理することができません。開発者の責任です。シリアルポート経由で1日に何千ものクーポンを処理するスキャンアプリケーションがあり、問題はありません。 .NETとのシリアルポート通信を適切に調査して、何をしているのか、何が起こっているのかを理解しましたか?スレッディングは複雑で、交通規則を学ぶことなく大都市で車を安全に走らせることができると考えている以上に、それを理解することなくそれをやることは期待できません。 – David

+0

あなたは 'ProcCntrlSSPortDataReceived'関数でスレッドを作成すると言っていますか?あなたはそこで何をしているのですか?おそらく、スレッドを作成する場所が問題です。 – SwDevMan81

+0

シリアルポートを処理するために独自のスレッドを使用しませんでした。つまり、.NetのSerialPortクラスは、シリアルポートを扱うスレッドを作成すると思います。 – 5YrsLaterDBA

答えて

2

How does SerialPort handle DataReceivedは何が起こっているのかを説明します。

DataReceived呼び出しがThreadPoolを使用し、QueueUserWorkItemを呼び出すように見えます。これは、データを十分速く処理しなければ、通話が待ち受けているように見えることを意味します。

カウントを(テストとして)保持したい場合は、BytesToReadを使用してイベントを受信して​​から、読み込んだ各文字を「処理」すると、すべてのバイトを試してみることができます。ポストで提案されているもう1つの選択肢は、データを受け取ったときに処理を実行するための独自の「処理」スレッドを作成することです。

あなたは、同時にアクティブにできるスレッドプールへの要求の数を設定します

ThreadPool.SetMaxThreads

を使用してのThreadPoolに作成されたスレッドの最大数を設定することができますようにそれはまた見えます。その数を超えるすべての要求は、スレッドプールスレッドが使用可能になるまで、キューに入れられたままです。

しかし、これはすべて、キューイングが行われている場所を変更することです。最終的には、なぜそれが遅れているのかを修正する必要があります。

1

SwDevMan81によると、DataReceived(.NETの他の多くの非同期イベントと同様)はThreadPoolスレッドで発生します。 ThreadPoolスレッドで行うべきではないことがいくつかあります。何も待たないでください。つまり、ファイル操作をブロックしない、WaitForSingleObjectを使わない、ISynchronizeInvoke.Invokeを使わないでください。それがブロックされないことを確認してください(長い間)。そうしないと、ThreadPoolはThreadPool.MaxThreadsの制限(IIRCが非常に高い)に達するまで、新しい作業項目がエンキューされたときに新しいスレッドを開始するだけです。

これが問題かどうかを調べる最も簡単な方法は、ThreadPool.GetAvailableThreadsを見ることです。時間の経過とともに減少する場合は、独自のスレッドを作成してデータを処理し、スレッドセーフキューに入れるだけですProcCntrlSSPortDataReceivedにあります。

関連する問題