2010-08-04 91 views
5

我想要使用後臺工作人員爲了從數據庫中檢索大量數據而不會拖延主線程。這似乎工作得很好,除了更新UI時,更新凍結了屏幕。相關代碼如下:C#後臺工作人員用戶界面更新

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    {    
     lvwTest.BeginUpdate(); 
     lvwTest.Items.Clear(); 

     // Populate the UI 
     foreach (TestItem ti in testData) 
     { 
      ListViewItem lvi = lvwTest.Items.Add(ti.Value1); 
      lvi.SubItems.Add(ti.Value2); 
     } 

     lvwTest.EndUpdate();      
    } 

更新大約需要2-3秒,這段時間屏幕被鎖定。我意識到只有主線程才能更新屏幕,但是有可能以某種方式將此數據加載到內存中(在後臺線程或另一個ListView實例中),然後只顯示它?我想要發生的只是讓程序在不佔用主線程時間的情況下刷新數據。

回答

1

我建議將數據加載到內存中並使用虛擬模式ListView。這樣,您只需要創建ListViewItem對象。

1

如果您必須將非常大量的數據加載到用戶界面中,它將需要時間並且會阻止我們的應用程序。該選項是智能滾動或分頁。您可以加載所有數據,但可以根據用戶請求一塊一塊地加載。

0

除了虛擬化之外,我還會建議將這些項目分成100個批次,並在每個批次中添加自己的消息。這樣,當批次被添加到ListView時,UI有改變來處理其他消息。

換句話說,所有RunWorkerCompleted處理程序都是排隊的第一批添加到一個單獨的消息。然後添加方法將添加項目,然後排隊下一批。這將繼續,直到沒有更多項目要添加。此時,您將重新啓用您的用戶界面的相關部分(ListView)。

0

由於以上大部分內容都是很好的建議,但並不能真正解決您的直接問題,因此可以採用另一種方法: 這會更新您的GUI並使其保持響應。假設你在WinForm應用程序?

 Application.DoEvents(); 
     this.Refresh(); 

然而,這並不意味着,也許你不應該從上面:-)聽取意見

+0

這是一個WinForm的應用程序 - 但早在VB6的日子裏,是的DoEvents時,因爲它可以皺起眉頭改變事件的順序。 C#中不是這種情況嗎? – 2010-08-05 11:53:19

+0

你可能是對的,從我聽到的內容來看,這仍然是一個黑客。取決於你的應用程序的複雜性。 我已經將我最後一個簡單的應用程序重寫爲WPF,這實際上是一個非常好的框架。 – Remy 2010-08-06 07:18:12