0

我即將編寫一個從TCP端口獲取流數據的應用程序,對它們進行一些實時計算。到目前爲止,所有這一切都很好,但是當生產者線程開始在數據塊上進行一些打包時(參見代碼),用戶界面和選取框進度條會卡住(對於不規則的短時間段)。UI線程被快速使用BlockingCollection卡住了?

 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在流式傳輸過程中顯示CPU使用率爲100%,每個塊包含大約2000個浮點值,其中4個或5個每秒都在沖刷一次。我也禁用了Logger,但沒有效果。消費者和評估線程被禁用。

除了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] =新線程(產生); myThreads [0] .Name =「Produce」; myThreads [0]。開始();」

+0

目前還不清楚您發佈的代碼在哪裏運行,或者您實際發生了哪些線索...請澄清您的情況。 –

+0

add方法似乎有點奇怪,但塊必須每個確實有500個val,並且必須保持連接到它們的通道,這很難通過大量數據保證。除此之外,出於性能原因,我不會想要使用刪除字典或BC,因爲它非常昂貴,所以我更新而不是刪除和添加。但添加方法不是問題,只要生產者不訪問BlockingCollection'bcPort',它就運行得非常流暢和快速。 – Rome

回答

1

它不是真的卡住了,你只是給它太多的工作要做。這使得它不再考慮低優先級任務,響應輸入和繪製通知。這確實讓它看起來像是卡住了,你的用戶一定會這麼想的。

關鍵是僅以對人眼有意義的速率更新用戶界面。除了超出每秒25次更新的模糊之外,它無法感知任何東西。如果你每秒鐘將它更新到千次更新,你將會得到你描述的行爲。因此,收集結果並且在足夠的時間到期之前不要調用/更新。一般而言,您將顯示的信息壓縮成可消耗的塊,以便爲用戶提供有意義的反饋,每秒顯示數百個新項目的列表對任何人都沒有用處。

+0

謝謝。日誌文件只是爲了幫助我,看看事情是否正確。對於用戶反饋,我有一個評估程序,它只會每秒向gui調用處理塊的基準測試。所以我的問題更多的是一個美容問題,並且選取框進度條似乎不適合顯示連續處理。有沒有另一種好方法來顯示在這樣一個計算密集的情況下(除了我的基準)用戶的不斷進步? – Rome

+0

任何事情都有可能,一個簡單的櫃檯就可以做到。您的摘錄太不透明,無法提供具體的建議。 –