在不同的线程中填充ObservableCollection

时间:2013-03-28 18:08:34

标签: c# wpf

我正在使用一个继承IEnumerable的类来检索DataType的集合。

class DataCollector : IEnumerable<DataType>
{
    public IEnumerator<DataType> GetEnumerator()
    {
        // this takes from 5 to 20 seconds,
        // so I want it to run in a background thread.
    } 
}

现在只需 Name Value 属性,DataType非常简单。

在我的ViewModel中:

private AsyncObservableCollection<DataType> _Data = new AsyncObservableCollection<DataType>();

我正在使用here中的AsyncObservableCollection,因此我可以从BackgroundWorker中填充它。

ViewModel中的构造函数创建了一个BackgroundWorker,这是DoWork:

void DoWork(object sender, DoWorkEventArgs e)
{
    var data = new DataCollector();
    foreach (var i in data)
    {
        _Data.Add(i);
    }
}

我得到Must create DependencySource on same Thread as the DependencyObject.
这是否意味着我需要在UI线程中创建我从DataCollector.GetEnumerator()中产生的DataType?我怎么能绕过这个?

3 个答案:

答案 0 :(得分:0)

为什么不等待整个事情完成,然后将项目的插入封送到UI线程?

void BackgroundWorker_Completed(ect... Im not used to work with BW so I don't know the parameters)
{
    _Data.AddRange(yourdataItems);
}

修改

如果要逐步填充observablecollection:

void DoWork(object sender, DoWorkEventArgs e)
{
    var data = new Datacollector();
    foreach (var i in data)
    {
        Application.Current.Dispatcher.BeginInvoke((Action)(_Data.Add(i)));
    }
}

答案 1 :(得分:0)

如果您有能力升级到.NET 4.5,那么该版本的WPF改进之一就是能够在后台线程上修改集合。有关详细信息,请参阅here

否则,在之前的版本中,您应该尝试仅通过使用Dispatcher.BeginInvokeDispatcher.Invoke或其他同步机制来修改UI线程上的集合。

答案 2 :(得分:0)

您可以使用BackGroundWorker ReportProgess传回对象(ObservableCollection)

BackgroundWorker.ReportProgress Method (Int32, Object)

一次传回100或1000行 或者只是传回前1000,然后等待完成获得总数。