从UI线程以外的线程更新绑定到ComboBox的BindingLIst

时间:2012-08-06 11:47:27

标签: c# wpf thread-safety bindinglist

我正在尝试在我的WPF应用中绑定一些BindingListComboBox控件。但是,我的BindingList是从UI线程以外的其他线程更新的。

我编造了一个模型。您只需要新的空项目,引用WindowsBase,PresentationCore,PresentationFramework,System.Xaml(或者只是将其放入预定义的WPF窗口)。

using System;
using System.ComponentModel;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

public class MainWindow : Window
{
    [STAThread]
    public static void Main()
    {
        new MainWindow().ShowDialog();
    }

    public MainWindow()
    {
        BindingList<string> list = new BindingList<string>();
        ComboBox cb = new ComboBox();
        cb.SetBinding(ComboBox.ItemsSourceProperty, new Binding() { Source = list });
        this.Content = cb;
        list.Add("Goop");
        new Thread(() =>
        {
            list.Add("Zoop");
        }).Start();
    }
}

Goop行中,一切正常。但是,当它到达Zoop行时,会产生异常:

  

此类型的CollectionView不支持对其进行更改   来自与Dispatcher线程不同的线程的SourceCollection。

在真实项目中,我无法将list.Add移动到UI线程,我想保留Binding问题。怎么解决?我可以转到其他“列表”而不是BindingList。我尝试过简单的List<string>,但情况更糟:当我添加新项目时它根本不会更新。

修改

实际上,添加线程知道列表,但它不知道WPF窗口。该列表在课堂上有内部工作,GUI检查类并查看它。因此,Add不应该知道GUI。

2 个答案:

答案 0 :(得分:0)

UI线程已锁定。 然后你必须在一个特殊的功能中提供你的数据。 MSDN BeginInvoke

使用:

BeginInvok(()=>{ // Your stuff});

您会要求用户界面尽快更新您的观看次数。

答案 1 :(得分:0)

试试这个,

  new Thread(() =>
  {
      if (cb.Dispatcher.CheckAccess())
        {
           list.Add("Zoop");
        }
      else
       {
        cb.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
                new Action(delegate 
                         {
                           list.Add("Zoop");
                         }
       ));
       }
  }).Start();

希望这会有所帮助