11

一度に数秒間実行されるスレッド(100)がいくつかあります。それらが実行されているとき、それらは別のシステム(シリアルデバイス)からの応答を待つためにその時間のかなりの時間を費やします。一度に100個のスレッドを実行することはリソースを大量に消費する可能性があることを念頭に置いているので、実際には一度に開始できるスレッドの数を制限しています。

スレッド内で外部イベントを待つには良い方法と悪い方法があるはずですが、私には思い浮かびます。このアプローチはCPUを集中的に使用しますか?:

send command ;
repeat
until response arrived ;
process response ;    

そして、このアプローチはそれをより効率的にしますか?:

send command ;
repeat
    Sleep (20) ;
until response arrived ;
process response ;  

* 追加情報 *

環境はx86WindowsXPです。スレッドコードは、シリアルデバイスとの長く複雑な一連の対話ですが、一般に、COMポートに文字を書き込み(AsyncFreeシリアルライブラリを使用)、着信文字バッファにキャンプして文字が返されるのを待機します。それらが到着したときにそれらを処理します。シリアルライブラリがデバイスの読み取りと書き込みを行うと思います。スレッド内の時間は、1分から数秒まで長くなる可能性がありますが、その時間のほとんどは、文字がポートを離れるのを待つか、応答文字を待つ(ボーレートが遅い)ために費やされます。したがって、スレッドが待機中に動作するための最良の方法についての私の質問。現在、私はSleepループで呼び出していますCharactersInBufferゼロ以外になり、各文字が到着したときに処理し、完全な応答が得られたらスレッドを終了します。したがって、コードは次のようになります(タイムアウトの処理などを無視します)。

send command ;
Packet = '' ;
repeat

    repeat
        Sleep (20) ;
    until response character arrived ;
    build Packet

until complete packet arrived
process response ;  
4

3 に答える 3

7

スレッドがプロセッサ時間を使用しないWaitForSingleObjectのようなもので本当に待機していて、タイムアウトした場合、スリープ状態のスレッドに遅延を置く理由はありません。

ユーザーはスレッドが応答するのを待っておらず、プロセッサー時間を使用しておらず、他のスレッドがブロックされないため、スレッドをスリープ状態にする理由はありません。

David Heffernanがコメントで示したように、現在CPUを100%使用していなければ、問題はありません。

シングルスレッドで、シリアルポートが応答するのを待つ間にユーザーに応答する必要がある場合は、sleep()を使用できます。

また、スレッドスリープを設定しても、効率は向上しません。それは単に他のスレッドにプロセッササイクルをもたらすでしょう。

sleep(0)スレッドで「時間を無駄にする」CPU効率の高い方法として見てください。

于 2011-11-01T19:41:18.383 に答える
2

スレッドがCPU時間を使用しないようにする最も効率的な方法は、スレッドを「待機モード」にすることです。

私はデルフィをまったく使用していませんが、その基本はそこにあるようです。「第11章シンクロナイザーとイベント」、より具体的には「セマフォを使用したイベントシミュレーション」を参照してください。

CPUを使用せずに待機する場合は、次を使用しますWaitForEvent

イベントの信号状態が調べられます。イベントが通知されたことを示している場合は、内部セマフォが通知され、セマフォでブロックされているスレッドの数が減少します。次に、ブロックされたスレッドの数が増加し、内部セマフォで待機が実行されます。

これがI/O関連の場合、動作は少し異なります。ソケットの場合はすでにブロックされている可能性があり、非同期I / Oの場合は、セマフォなどを使用できますWaitForEvent

.NETには、、、、Monitor.Waitなどがありますが、delphiで同等のものが何であるかはわかりません。Monitor.SignalManualResetEventCountDownLatch

于 2011-11-01T19:44:52.713 に答える
2

AsyncFreeの機能について話すことはできませんが、一般にWindowsのCOMポートプログラミングはオーバーラップI / Oをサポートしているため、などの関数ファミリーのWaitCommEvent()1つで関数を使用することにより、データが到着したときの通知を効率的に待つことができます。スレッドは、通知が発行されるまでスリープ状態にすることができます。発行されると、スレッドは「ウェイクアップ」してポートから読み取り、それ以上読み取ることがなくなるまで読み取り、次の通知までスリープに戻ることができます。WaitFor...()WaitForSingleObject()

于 2011-11-02T01:41:12.267 に答える