TCP ポートからストリーミング データを取得し、リアルタイムで計算を行うアプリケーションを作成しようとしています。これまでのところすべて問題ありませんが、プロデューサー スレッドがデータ チャンクのパッケージ化を開始するときに、ユーザー インターフェイスとマーキー プログレス バーが (不規則な短い期間) 動かなくなります (コードを参照)。
void Produce()
{
try
{
while (true)
{
foreach (Chunk _chunk in bcPort)
{
if (_ThreadCanceler.IsCancellationRequested) break;
Chunk chunk = bcPort.Take();
chunk.TimeTracker = new Stopwatch();
chunk.SegmentId = iSegmentId;
if (chunk.Channel + 1 == iChannels) iSegmentId++; // last channel, raise segment id.
iPrevChannel = chunk.Channel;
// _ProcessAndJoin.EnqueueTask(chunk, _ThreadCanceler);
iChunksProduced++;
_LogWriter.WriteMessage("Task " + Task.CurrentId.ToString() + "(producer): ADDED_ Chunk[" + chunk.Channel + ":" + chunk.Vals.Count.ToString() + ":" + chunk.SegmentId + "] [" + iChunksProduced + "]. " + bcPort.Count + " for takeaway. Thread: " + Thread.CurrentThread.ManagedThreadId.ToString());
}
if (_ThreadCanceler.IsCancellationRequested) break;
}
}
catch (Exception ex)
{
Console.WriteLine("ForkAndCrate.cs: Produce(): " + ex.ToString());
}
}
多くのテストを行ったところ、BlockingCollection bcPort へのアクセスが問題のようであることがわかりました。bcPort は、UI スレッドに影響を与えないはずの別のデータ加算スレッドから常にチャンクを取得します。したがって、次のことがわかりません。
1.) チャンクの追加とパッケージ化に別のスレッドを使用すると、GUI が動かなくなるのはなぜですか?
2.) データの保存に BC を使用しているのに、なぜこのようなことが起こるのですか? これらの特定の目的のためのスレッド セーフ コレクションではありませんか?
ちなみに、Windows 7 の ResourceManager は、ストリーミング中に 100% の CPU 使用率を示します。チャンクにはそれぞれ約 2000 の浮動小数点値が含まれており、そのうちの 4 つまたは 5 つが毎秒急いでいます。ロガーも無効にしましたが、効果はありません。コンシューマー スレッドと評価スレッドは無効になっています。
UI スレッドのほかに、"ReceiveAndSave" と呼ばれるスレッドだけがあり、受信する float 値からチャンクを作成します (コード、メソッド "Add" を参照)。スレッド「プロデューサー」はさらにパッケージ化を行っており、コンシューマー (非アクティブ化) のチャンクをキューに入れています。
public void Add(short iChannel, float fValue)
{
try
{
_Benchmark.UpdateRec(); // one value received, update benchmark:
if (!cdBasin[iChannel].Enqueue(fValue))
{
Chunk chunk = new Chunk();
chunk.Vals = cdBasin[iChannel].ToListDeep;
chunk.Channel = iChannel;
bcPort.Add(chunk);
cdBasin.AddOrUpdate(iChannel, new BoundedQueue<float>(iSegmentSizePerChannel), (key, oldValue) => new BoundedQueue<float>(iSegmentSizePerChannel));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Stop", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
}
プロデューサーは 'myThreads[0] = new Thread(Produce); で開始されます。myThreads[0].Name = "プロデュース"; myThreads[0].Start();'