0

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();'

4

1 に答える 1

1

本当に行き詰まるわけではありません。ただ、あまりにも多くの仕事を与えているだけです。これにより、優先度の低いタスクを処理しなくなり、入力とペイントの通知に応答します。実際にスタックしているように見えるので、ユーザーは確かにそう思います。

重要なのは、人間の目で理解できる速度でのみ UI を更新することです。これは、1 秒あたり 25 回の更新を超えるぼかし以外は何も認識できません。1 秒あたり最大 1000 回の更新にプッシュすると、説明した動作が得られます。したがって、結果を収集し、十分な時間が経過するまで呼び出し/更新しないでください。また、一般に、ユーザーに意味のあるフィードバックを提供するために、表示する情報を消費可能なチャンクに圧縮します。1 秒間に何百もの新しいアイテムを表示するリストは、誰にとっても役に立ちません。

于 2012-05-28T16:19:07.840 に答える