2013-02-13 78 views
2

我正在將一個大的Txt文檔讀入WPF應用程序中,以進行一些嚴重的交換/替換操作。這些文件實際上是3D STP模型,因此它們相當大,但我正在將它們作爲該項目的原始文本進行處理。這些文件被讀入列表以避免多次打開它們,並使比較更容易。將.TXT實時讀入列表框

無論如何,我試圖讓列表框動態滾動,因爲行被添加到它,ala控制檯窗口,因此用戶可以看到發生了一些事情,因爲計算可能需要一些時間取決於文件大小。我還添加了一個進度條來計數,因爲總行數是通讀的。

我的進度條和ListBox似乎都不會隨着工作進度而更新。最終的輸出完全落在列表框中,同時進度條從0-max開始。

這是我在做什麼的要點,這是相當簡單:

foreach (string Line in OriginalSTPFile.Lines) 
    { 
     string NewLine = EvaluateString(Line); //string the modified to whatever here 
     pBar.Value++; //increment progressbar 

     OutputWindow.Items.Add(NewLine); //add line to the ListBox 
    } 

我只想列表框中的進度條實時的進展變化進行更新。我試過使用:

Dispatcher.BeginInvoke(new Action(() => OutputWindow.Items.Add(NewLine)); 

但是得到了同樣的結果。我需要更復雜的多線程方法嗎?我假設第一種方法會起作用,因爲我沒有產生任何交叉線程異常。

+0

你是什麼意思與「實時」的僞代碼?什麼是相當大的?請同時發佈更新進度條的步驟功能。 – 2013-02-13 20:10:25

+0

如同一樣,每當一條線被「評估」時,結果立即被打印到列表框中,並且相應地移動演算條。應該在下一行被評估之前發生。現在,該程序暫時掛起,然後所有信息同時出現。 – 2013-02-13 20:13:50

+0

請看我的答案。它肯定會幫助你。 – 2013-02-13 20:43:32

回答

1

Dispatcher.BeginInvoke信號調用Dispatcher線程上的方法。但是,這基本上就像是一條郵件消息,因爲在主線程被鎖定工作時它不會發生。直到主線程再次可用,它不會以可視方式更新UI,即使您更改了值。

您需要在後臺線程中執行該工作。

但是要更新UI,您必須在UI的主線程上這樣做。這是WPF的限制。這就是爲什麼你被引導到分派器。我猜猜有人認爲你的工作已經在後臺線程上。

要創建一個線程,請使用Thread.Start傳遞一個委託來執行。如果您使用匿名委託或lambda表達式,則可以引用堆棧中的變量,但請注意,它們將一直存在,直到委託退出。這就是爲什麼你不能在匿名代理中使用引用變量的原因。

Backgroundworker是一種特殊類型的後臺線程。它自動化了工作線程的一些期望(通知完成和更新進度),但是如果沒有它,你可以獲得相同的結果。

要在線程進程中更新UI,您需要該線程能夠訪問主UI線程。你可以通過傳遞一個調度器,引用一個來自匿名委託之外的調度器,或者一個包含調度器的對象。你可以隨時讀取任何線程上的任何對象的值,因此在另一個線程上通過UIElement訪問調度器就沒有問題。

要更新用戶界面,您可以撥打Dispatcher.BeginInvoke與需要執行工作的委託。

這裏的總體方案

class TestProgress 
{ 
    ProgressBar _ProgressBar; 

    void DoWork() 
    { 
     var worker = (Action)(() => 
     { 
      int progress = 0; 
      // do stuff, delta is change in progress 
      progress += delta; 
      _ProgressBar.Dispatcher.BeginInvoke((Action)(() => 
      { 
       _ProgressBar.Value = progress; 
      })); 
     }); 
     Thread.Start(worker); 
    } 
} 
+0

這兩個答案都非常好,我希望我可以選擇兩個!足夠的話,除非我在我的DoWork方法中包含Thread.Sleep(1),否則顯示仍然不會更新。它在後臺執行,我可以移動UI,但不會動態更新。 – 2013-02-13 20:54:48

+1

嘗試調用而不是BeginInvoke – 2013-02-13 21:00:09

+0

就是這樣!我有很多需要關注多線程的東西!謝謝 – 2013-02-13 21:04:33