2017-08-14 31 views
-1

我想使用BackgroundWorker來爲我收集一些數據,並在我的窗體中更新ListView,同時我顯示一個進度條並允許gui不被凍結。 當我嘗試使用BackgroundWorker更新我的ListView時,出現跨線程錯誤。爲了克服這個問題,我在BackgroundWorker中填充一個臨時ListView,並將其分配給結果,然後使用來自backgroundWorker1_RunWorkerCompleted的填充來填充我的原始ListView。如何正確使用BackgroundWorker更新ListView? [c#.NET 3.5]

#1:有沒有一種更優雅的方式來更新/顯示我的ListView,而無需在_RunWorkerCompleted中創建另一個臨時ListView?

#2:有沒有辦法將原始listview作爲參數傳遞給backgroundWorker?

我很欣賞這方面的任何反饋。

在此先感謝!

僞代碼

// Original ListView in Form 
ListView orginalListView = new ListView(); 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    ListView backgroundList = new ListView(); 
    foreach(var data in database) 
    { 
     listViewItem = data.value; 
     backgroundList.Items.Add(listViewItem); 
    } 
    e.Result = backgroundList; 
} 


private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
     // Can I avoid needing to create a temp LV ?? 
     ListView tempLV = new ListView(); 
     tempLV = (ListView)e.Result; 


     foreach (ListViewItem item in tempLV.Items) 
     { 
      orginalListView .Items.Add((ListViewItem)item.Clone()); 
     } 
} 

回答

1

要更新跨線程的用戶界面,你需要調用一個新的 代表。檢查調用此此鏈接的信息: Invoke

是的,你可以做,在一個優雅的方式,而不需要其他臨時的ListView:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    foreach (var data in database) 
    { 
     if (orginalListView.InvokeRequired) 
     { 
      orginalListView.Invoke(new MethodInvoker(delegate 
      { 
       listViewItem = data.value; 
       orginalListView.Items.Add(listViewItem); 
      })); 
     } 
     else 
     { 
      listViewItem = data.value; 
      orginalListView.Items.Add(listViewItem); 
     } 
    } 
} 
+1

也許可以解釋一下調用調用。這裏有一個相關的[鏈接](https://msdn.microsoft.com/en-us/library/zyzhdc6b(v = vs.110).aspx)。 –

+1

感謝您的快速反應和描述鏈接!我可以確認這種方法對我有用 – AlkiZaganiaris

-1

你可能只需要鎖定資源而線程正在訪問它。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    foreach(var data in database) 
    { 
     listViewItem = data.value; 
     String name = "orginalListView"; 

     lock (((ListView)this.Controls[name])) 
     { 
      //Update UI, invoked because on different thread. 
      Invoke(new MethodInvoker(delegate { ((ListView)this.Controls[name]).Items.Add(listViewItem); })); 
     } 
    } 
} 
+0

爲什麼我的排名降低,而另一個排名卻是一個非常相似的答案,但代碼更多? –

+0

我沒有投票,但我最好的猜測是你說你需要鎖定資源,但沒有解釋爲什麼。據我的理解,鎖定它不是必要的,但我肯定是錯的,在線程方面,我並不專業。 –

+0

感謝您的快速響應!不知道爲什麼它排名下來.. @ st3_121 – AlkiZaganiaris

相關問題