如何绑定到ObservableCollection< T>正在更新Async或在另一个线程中 [英] How do I bind to ObservableCollection<T> which is being updated Async or in another thread

查看:92
本文介绍了如何绑定到ObservableCollection< T>正在更新Async或在另一个线程中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的ViewModel中,我有一个Point类型的ObservableCollection,它绑定到View中图表的一个系列。当用户单击按钮时,将对执行计算密集型计算的方法进行异步调用,并在整个过程中更新ObservableCollection。



当它到达更新ObservableCollection中的元素的行会抛出 InvalidOperationException ,其中的解释是调用线程无法访问此对象,因为其他线程拥有它。我知道这是因为我正在尝试更改绑定到UI线程上的控件的对象。



人们通常如何处理这个问题?我希望有一个非常干净和直截了当的方式?或者我是否必须使用委托来调用ObservableCollection?







更新更多信息:



启动异步方法时,我没有使用 .ConfigureAwait 。简单地说:

< br /> 
await Task.Factory.StartNew(()=> methodName(parameter1));





我试图让这个工作时收集的更多信息。最初我有一个 ObservableCollection ,类型为 System.Windows.Point ,其 X 以及图表中使用的 Y 属性。因为 X Y 没有 Set 属性我不得不创建一个新的 Point 元素,看起来像

< br /> 
observableCollection1 [0 ] = new System.Windows.Point(newPointX,newPointY);< br />





它在那一行<抛出code> InvalidOperationException 。



我尝试了另一种创建类型为 Point List 的方法c $ c>并将每个新的newXPoint和newYPoint值添加到列表中,然后在循环外部创建一个使用 List ObservableCollection 对象code>元素如下:

< br /> 
observableCollection1 = new ObservableCollection< system.windows.point>(tempList);< / system.windows.point>





这不会抛出 InvalidOperationException 而且似乎工作正常。我想这可能是更好的方法,因为NotifyPropertyChanged事件只会触发一次,而不是每次元素设置为 Point 对象的新实例。这是正确的吗?



无论哪种方法更好,我仍然很困惑为什么我得到InvalidOperationException。有什么想法?

解决方案

如果你使用的是.NET 4.5,你可以使用 BindingOperations.EnableCollectionSynchronization 方法 [ ^ ]允许您从其他线程更新集合:

  private   static   object  _lock =  new  对象(); 
private readonly ObservableCollection< Point> _points = new ObservableCollection< Point>();

public YourViewModel()
{
BindingOperations.EnableCollectionSynchronization(_ points,_lock);
}



WPF 4.5中的数据绑定功能 - DotNetCurry [ ^ ]



或者,如果您使用 async / 等待 (在你的等待中不使用 .ConfigureAwait(false),代码应始终在UI线程上运行,你永远不应该看到这个异常。


In my ViewModel I have a ObservableCollection of type Point which is bound to one of the chart's series within the View. When the user clicks a button the an asynchronous call is made to a method which executes a computationally intensive calculation and updates the ObservableCollection throughout the process.

When it gets to the line that updates an element within the ObservableCollection an InvalidOperationException is thrown with the explanation that "The calling thread cannot access this object because a different thread owns it." I understand that this is occurring because I am trying to change an object which is bound to a control on the UI thread.

How do people typically deal with this problem? I'm hoping there is a very clean and straightforward way? Or do I have to make a call using a delegate to invoke on the ObservableCollection?



Update with more information:

I didn't use the .ConfigureAwait when launching the asynchronous method. Simply:

<br />
await Task.Factory.StartNew(() => methodName(parameter1));



A little more information I gathered while trying to get this to work. Initially I had an ObservableCollection of type System.Windows.Point which has an X and a Y property which is being used in the chart. Because the X and Y do not have a Set attribute I had to create a new Point element looking something like

<br />
observableCollection1[0] = new System.Windows.Point(newPointX, newPointY);<br />



It is at that line where the InvalidOperationException is thrown.

I tried it another way of creating a List of type Point and added each new newXPoint and newYPoint value to the list and then outside the loop created a new ObservableCollection object initialized with the List elements like so:

<br />
observableCollection1 = new ObservableCollection<system.windows.point>(tempList);</system.windows.point>



This does not throw the InvalidOperationException and seems to work fine. I imagine this is probably the better way to do it as well since the NotifyPropertyChanged event will only fire once instead of every time that an element set to a new instance of a Point object. Is that correct??

Regardless of which method is better I am still very confused why I am getting the InvalidOperationException. Any thoughts?

解决方案

If you're using .NET 4.5, you can use the BindingOperations.EnableCollectionSynchronization method[^] to allow you to update the collection from other threads:

private static object _lock = new object();
private readonly ObservableCollection<Point> _points = new ObservableCollection<Point>();

public YourViewModel()
{
    BindingOperations.EnableCollectionSynchronization(_points, _lock);
}


DataBinding Features in WPF 4.5 - DotNetCurry[^]

Alternatively, if you use async / await (without using .ConfigureAwait(false) on your awaitables), the code should always run on the UI thread, and you should never see this exception.


这篇关于如何绑定到ObservableCollection&lt; T&gt;正在更新Async或在另一个线程中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆