2017-02-04 15 views
1

我有一個WPF應用程序,我想將項目添加到許多線程上的列表框。 當我做這樣的事情在許多線程上添加項目到列表框時出錯

 listBox.Items.Clear(); 
     var lastgames = db.GameResults.OrderByDescending(c => c.DataGry).ToList(); 
     Parallel.ForEach(lastgames, game => 
     { 
      listBox.Items.Add(game.score); 
     }); 

它顯然拋出和異常

,因爲不同的線程擁有它調用線程不能訪問該對象。

我聽說過WPF的背景工作,但我不知道如何使用它。

+1

你不能觸及UI線程以外的其他線程的UI對象...你可以在WinForms上使用Invoke,或者在wpf中使用Dispatcher ...但是你應該使用MVVM這樣的好模式來修改ViewModel和視圖反映視圖模型中的變化......不編寫邏輯將項目直接添加到UI控件中 –

+0

要處理導致UI被鎖定的長操作或操作,您需要使用「ThreadPool」和「Dispatcher.Invoke」。例如:http://stackoverflow.com/questions/36521365/run-program-after-wpf-windows-form-appears –

+0

@ S.Akbari一直使用你的代碼,並替換parallel.foreach到正常的foreach是我應該做的? – kociolekpanoramixa

回答

0

由於UI元素只能從他們最初的創建上,即UI線程的線程進行訪問,這是沒有意義的使用Parallel.ForEach項添加到列表框。

你應該用一個簡單的foreach循環:

listBox.Items.Clear(); 
var lastgames = db.GameResults.OrderByDescending(c => c.DataGry).ToList(); 
foreach(var game in lastgames) 
    listBox.Items.Add(game.score); 

另一種選擇是將商品加入一個線程安全的集合,然後設置ListBox的ItemsSource屬性來此集合一旦被填充:

object _lock = new _lock(); 
List<int> scores = new List<int>(); 
listBox.Items.Clear(); 
var lastgames = db.GameResults.OrderByDescending(c => c.DataGry).ToList(); 
Parallel.ForEach(lastgames, game => 
{ 
    lock (_lock) 
     scores.Add(game.score); 
}); 
listBox.ItemsSource = scores; 

雖然你仍然需要在循環的每次迭代中同步對集合的訪問,但這樣做毫無意義。所以你最好使用一個簡單的foreach循環,並將所有項目添加到同一個線程中。

+0

阻止收集是我正在尋找的。謝謝你解釋。 – kociolekpanoramixa

+0

不客氣。請記住投票了有用的答案:http://stackoverflow.com/help/privileges/vote-up – mm8

0

您不能使用UI線程以外的其他線程的UI控件。您應該使用調度程序。

對於前:

Application.Current.Dispatcher.BeginInvoke(
    DispatcherPriority.Background, 
    new Action(() => { 
     listBox.Items.Add(game.score); 
}));