在多个线程上向列表框添加项目时出错

时间:2017-02-04 12:19:15

标签: c# wpf multithreading listbox

我有一个WPF应用程序,我想在许多线程上向listbox添加项目。 当我做这样的事情时

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

它显然会抛出异常

  

调用线程无法访问此对象,因为另一个线程拥有它。

我听说过WPF中的后台工作者,但我不知道如何使用它。

2 个答案:

答案 0 :(得分:0)

您不能使用UI线程以外的其他线程的UI控件。你应该使用调度员。

例如:

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

答案 1 :(得分:0)

由于UI元素只能从最初创建它们的线程(即UI线程)访问,因此使用Parallel.ForEach将项添加到ListBox是没有意义的。

你应该使用一个简单的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循环并在同一个线程上添加所有项目。