私は2つのスレッドを持っています。 1つは、シリアルポートからデータを収集し、それを配列に配置して、並行キューに追加することです。もう1つのスレッドは、これらの配列を取得して、データをリアルタイムでプロットしています。毎秒50バイトのデータの約150パケットがあります。私が抱えている問題は、これを実行すると、約10%のCPUを消費していることです。そして、これは非常に高速なコアI7Haswell上にあります。消費スレッドにThread.Sleep(1)を追加すると、CPU使用率が1%に低下します。問題は、これをThread.Sleep(2)に置くと、パケットが同期されなくなることです。したがって、これは解決策ではなく、低速のコンピューターで実行した場合、おそらく機能しません。
コードは単純です。これがプロデューサースレッドです:
static void FillQueue(byte[] buffer)
{
dataQueue.Enqueue(buffer);
}
そしてここに消費者スレッドがあります:
while (continuePolling)
{
Thread.Sleep(1); //if removed, there is 10% CPU utilization. If higher then packet synchronization is lost.
if (dataQueue.TryDequeue(out result))
{
ProcessPacket(result);
}
}
ProcessPacketメソッドの実行には約0.3ミリ秒かかり、1秒間に約10回呼び出されるため、これを理解するのは難しいと思います。
代わりにブロッキングコレクションを使用してみました。こちらがプロデューサーです
BlockingCollection<byte[]> dataQueue = new BlockingCollection<byte[]>;
public static void addData(buffer)
{
dataQueue.add(buffer);
}
そしてここに消費者がいます
while (dataQueue.TryTake(out result)
{
ProcessPacket(result);
}
全く違いはありません! 10%のCPUを使用し、Thread.Sleep(1)を追加しても問題ありませんが、Thread.Sleep(2)を使用すると、パケットが失われます。各パケットには50バイトがあります。それでおしまい。そして、それらは生産されるのと同じくらい速く消費されます。ありがとう
これは、基本的にwhile (true) {}
ループがあるためです。 ProcessPacket
は0.3ミリ秒かかり、1秒あたり10パケットあるため、1秒あたり3ミリ秒の有用な作業があります。残りの997msは、キューに新しいアイテムがあるかどうかをループが常にチェックし、CPUリソースを浪費します。
代わりに、キューと一緒にBlockingCollection
を使用してください。これにより、タスクにはるかに優れたオプションが提供されます。デキューのブロック(必要に応じてタイムアウトとキャンセルトークンを使用)をサポートしているため、CPUを浪費しません。
var dataQueue = new BlockingCollection<string>(new ConcurrentQueue<string>());
// Add instead of Enqueue
dataQueue.Add("some item");
// Take instead of Dequeue, this will block until item is available in queue
var result = dataQueue.Take();
// blocks until item is available or timeout happens
if (dataQueue.TryTake(out result, TimeSpan.FromMilliseconds(100)))
また、「ストリーミング」インターフェイスもサポートしているため、コードは次のようになります。
foreach (var result in dataQueue.GetConsumingEnumerable()) {
ProcessPacket(result);
}
そして、continuePolling
フラグの代わりに-呼び出します
dataQueue.CompleteAdding();
これ以上アイテムが期待されない場合(つまり、continuePolling
をfalseに設定する場合)-これにより、GetConsumingEnumerable
がアイテムの提供を終了して戻ります。