C# 将WPF控件绑定到由后台线程修改的ObeservableCollection

C# 将WPF控件绑定到由后台线程修改的ObeservableCollection,c#,wpf,data-binding,C#,Wpf,Data Binding,这是我生命的延续 这是我的mainwindow.cs public partial class MainWindow : Window { ObservableCollection<string> store; public MainWindow() { SerialPort _serialPort = new SerialPort(SerialCom.findCOMPort(), 115200, Parity.None, 8, StopBit

这是我生命的延续 这是我的mainwindow.cs

   public partial class MainWindow : Window
{
    ObservableCollection<string> store;
    public MainWindow()
    {
     SerialPort _serialPort = new SerialPort(SerialCom.findCOMPort(), 115200, Parity.None, 8, StopBits.One);
     _serialPort.Handshake = Handshake.None;
     string[] query = new string[3] { "t02", "t03", "t04" };
     store = new ObservableCollection<string> { " ", " ", " " };
     this.DataContext = this;
     Thread thread = new Thread(delegate(){Process(store,query,_serialPort);});
     thread.IsBackground = true;
     try
     {
        thread.Start(); //catch sudden serial port closure exception
     }
     catch (Exception)
     {
        thread.Abort();
     }
   }

 public static void Process(ObservableCollection<string> store, string[] query, SerialPort _serialPort)
 {          
     while (true)
     {             
         for (int i = 0; i < 3; i++)
         {
             string add = SerialCom.returnData(query[i], _serialPort);
             if (store[i] != add)
             {
                 store.Insert(i,add);
             }
         }             
         Thread.Sleep(300);

     }
 }
公共部分类主窗口:窗口
{
可观察收集存储;
公共主窗口()
{
SerialPort _SerialPort=新的SerialPort(SerialCom.findCOMPort(),115200,奇偶校验.None,8,stoppits.One);
_serialPort.Handshake=Handshake.None;
string[]query=新字符串[3]{“t02”、“t03”、“t04”};
store=新的ObservableCollection{“”,“”};
this.DataContext=this;
Thread Thread=新线程(委托(){进程(存储,查询,_serialPort);});
thread.IsBackground=true;
尝试
{
thread.Start();//捕获串行端口突然关闭异常
}
捕获(例外)
{
thread.Abort();
}
}
公共静态无效进程(ObservableCollection存储、字符串[]查询、SerialPort\u SerialPort)
{          
while(true)
{             
对于(int i=0;i<3;i++)
{
字符串add=SerialCom.returnData(查询[i],_serialPort);
如果(存储[i]!=添加)
{
存储。插入(i,添加);
}
}             
睡眠(300);
}
}

我在我的XAML页面中有一个WPF listview控件。我想将该控件绑定到非UI线程中正在更改的ObservableCollection。似乎美中不足的是,在程序运行时,我必须查询设备的无限循环。此外,由于ObservableCollection实现INotifyPropertyChanged,因此在绑定时如果从绑定系统使用ObservableCollection,则不允许从后台线程对其进行更新。这是因为更新通知(通过InotifyCollection)已更改在进行更改的线程上发生。对ObservableCollection的更改必须发送到UI线程。

在4.5中,使用
BindingOperations
类有一个很好的解决方案:

对于早期版本,您需要更新dispatcher线程上的集合,或者将更改通知事件推送到dispatcher线程:

当您将observablecollection绑定到listview时,它属于UI线程。如果您想更新集合,我认为您需要使用Dispatcher.BeginInvoke,一切都应该很好。这正是我所需要的。谢天谢地,我可以使用net 4.5分发!好的,我尝试通过codebehind使列表视图的ItemSource“存储”起来,但它抛出了错误“TargetInvocationException”,InnerException是“NullReferenceException”,这是我的新代码
store=newobserveCollection{“a”、“b”、“c”};BindingOperations.EnableCollectionSynchronization(store,_lock);//允许跨线程绑定thread thread=new thread(delegate(){Process(store,query,_serialPort);});thread.IsBackground=true;listview1.ItemsSource=store;
注释中的代码不太好。最明显要检查的是,您在调用
EnableCollectionSynchronization
方法之前设置了
\u lock
对象。奇怪的是,我得到了完全相同的exc如果我注释掉BindingOperations调用,则为eption。\u在调用该方法之前,lock是新的。在将ObservableCollection设置为ItemsSource之前,我确保它具有一些值。中列出的问题是否相关?听起来可能相关,特别是需要锁定自己对集合的访问。请尝试添加
锁(_lock){…}
if(store[i]!=add){store.Insert(i,add);}
块周围阻塞。