从工作线程访问UI线程集合

时间:2014-07-29 09:37:38

标签: c# wpf multithreading mvvm

我正在Visual Studio 2012中的c#wpf中编写一个应用程序。我正在使用mvvm。 我有一个属于UI线程的ObservableCollectionCriteriaCollection,用于从数据库中获取数据我正在使用Task.Factory,因为数据很大并且保存在远程服务器上。 当我点击GetData按钮后执行代码。 我的代码是这样的:

void GetData(object obj)
{
        if (CriteriaCollection == null)         
        CriteriaCollection = new ObservableCollection<Criteria>();

        if (SelectedIndex != null && SelectedCriteria != null)
        { 
                bool results = this.CriteriaCollection.Any(report => 
                     report.CriteriaName.Equals(
                                 this.SelectedCriteria.CriteriaName.ToString()));
                if (!results)
                {
                    Task.Factory.StartNew(() =>
                    {
                        IsBusy = true;
                        Criteria newCriteria = new Criteria();

                        ExecuteGetDataFromDB(null);

                      ///some code which populates values and fills newCriteria

                        CriteriaCollection.Add(newCriteria);
                        }).ContinueWith(result =>
                        {
                            IsBusy = false;
                        });
                }
        }    
}

我在CriteriaCollection.Add(newCriteria)行获得了一个例外;说This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread. 有人可以帮我吗?

谢谢!

2 个答案:

答案 0 :(得分:2)

GUI相关代码只能从GUI线程或另一个线程的调度程序执行:

Application.Current.Dispatcher.Invoke(new Action(() => 
{
    // your GUI related code here
}));

答案 1 :(得分:0)

创建任务以执行后台工作的代码不太正确,我相信你想要更像这样的东西:

        IsBusy = true;

        Task<SomeResult>.Factory.StartNew(() =>
        {
            Criteria newCriteria = new Criteria();
            return ExecuteGetDataFromDB(newCriteria);

        }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default)
        .ContinueWith(t =>
        {
            CriteriaCollection.Add(t.Result);

            IsBusy = false;
        }, TaskScheduler.FromCurrentSynchronizationContext());

这样做是在后台线程上创建任务,当它在UI线程上完成'继续'时,希望你不再得到例外。

请注意,您必须将SomeResult类定义为ExecuteGetDataFromDB方法的返回类型。