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”的线程从传入的浮点值中生成块(参见代码,方法“Add”)。线程“Producer”正在做一些进一步的打包并将消费者的块排入队列(停用)。

   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。除了每秒超过 25 次更新的模糊之外,它什么也看不见。如果您将其推送到每秒多达一千次更新,您将获得您描述的行为。所以收集结果并且在足够的时间到期之前不要调用/更新。而且通常将您显示的信息压缩成可消耗的块,以便为用户提供有意义的反馈,每秒显示数百个新项目的列表对任何人都没有用。

于 2012-05-28T16:19:07.840 回答