2014-12-23 115 views
0

我想補充項目的大數目的ListBox
首先我定義它抱到了特定
項目對象添加到列表框項集合
這是實現基於任務的異步方法的正確方法嗎?

delegate void D(); 

然後匿名方法的引用委託我寫異步方法

private async void AddAsync() 
{ 

     await Task.Run(() => 
      { 
       for (int i = 0; i < 40000; i++) 
       { 
        D r = new D(() => this.listBox1.Items.Add(i)); 
        this.listBox1.Invoke(r); 
       } 
      } 
      ); 
} 

這是實施TAP的正確方法嗎?
我犯了一個錯誤嗎?
從性能的角度來看,你能提出一個更好的邏輯嗎?或者這已經足夠好了

+1

有40,000個項目的列表框?我不確定這是否會飛,但如果堅持我認爲最好創建一個任務,將40,000個項目添加到列表框中,而不是創建40,000個任務,每個任務將單個項目添加到列表框中。 –

+0

哦,我犯了一個大錯,我編輯了方法,謝謝 –

+0

從性能的角度來看,這可能是你能做的最糟糕的事情。正如Martin所說,由於您正在更新必須在UI線程上完成的UI,因此在UI線程的單線程循環中執行此操作會更有效率。在UI環境中,一般來說,當這些長時間運行的操作的結果可用時,您希望將長時間運行的非UI相關**任務轉移到後臺,並且只在UI線程上調用它們,但在更新這種UI時,您最好在主線程中完成,而不是創建40,000個任務來完成它。 – kha

回答

1

正如其他人在評論中提到的那樣,整個後臺線程的要點是做後臺工作。在你的例子中,沒有後臺工作。整個後臺代理只是將工作發送到UI線程。

如果這實際上是代表你的代碼,你可能也只是做它直接在UI線程:

private void Add() 
{ 
    for (int i = 0; i < 40000; i++) 
    this.listBox1.Items.Add(i); 
} 

注意加入項目的UI是UI操作,所以必須在UI線程上完成。現在,如果創建項目需要一定的時間,那麼你可以從後臺的工作中受益:

private async Task AddAsync() 
{ 
    IProgress<int> progress = new Progress<int>(x => this.listBox1.Items.Add(x)); 
    await Task.Run(() => 
    { 
    for (int i = 0; i < 40000; i++) 
    { 
     int value = i; // TODO: replace this with the long-running create-item code. 
     progress.Report(value); 
    } 
    }); 
} 

注意使用IProgress<T>/Progress<T>避免過時Control.Invoke機制。

+0

謝謝,我想如果我使用後臺線程,那麼UI線程將不會做任何工作,對於這種誤解抱歉,請你解釋爲什麼使用後臺線程進行需要時間的操作是有用的,因爲在任何情況下UI線程將收到更新其控件的請求?我測試的代碼與依賴於UI線程的代碼差別很大 –

+0

@MadMass:後臺線程對於在另一個線程上執行*非UI工作*很有用。因此,如果需要花費一秒左右來創建每個項目,那麼可以通過後臺線程完成該工作,而UI線程只需要花費10ms左右的時間來添加項目。 –

相關問題