UI线程被快速使用BlockingCollection卡住了吗?

时间:2012-05-28 16:02:45

标签: .net multithreading c#-4.0 thread-safety blockingcollection

我即将编写一个从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个是每秒冲入。我也禁用了Logger但没有效果。消费者和评估线程被禁用。

除了ui线程之外,只有一个名为“ReceiveAndSave”的线程,它使传入的浮点值产生块(参见代码,方法“添加”)。线程“生产者”正在进行一些进一步的打包并将消费者的块排入队列(停用)。

   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 =“Produce”; myThreads [0]。开始();'

1 个答案:

答案 0 :(得分:1)

确实卡住了,你只是在做太多工作。这使得它不再处理其低优先级任务,响应输入和绘制通知。这确实使它看起来就像它被卡住一样,你的用户肯定会这么认为。

关键是只以对人眼有意义的速度更新UI。除了每秒超过25次更新的模糊之外,它无法感知任何东西。如果您将其推送到每秒多达一千次更新,您将获得您描述的行为。因此,收集结果,并且在足够的时间到期之前不要调用/更新。通常将您显示的信息压缩为可消耗的块,以便为用户提供有意义的反馈,列表显示数百个新项目,一秒钟对任何人都没用。