c#tpl,continuewith的问题“调用线程无法访问对象,因为不同的线程拥有它”

时间:2012-02-02 13:30:37

标签: visual-studio-2010 task-parallel-library

我正在运行Visual Studion 2010(Net 4.0) 我正在创建一个任务,将一些值加载到ObservableCollection中,然后返回到UI。这是代码:

LoadValues = Task.Factory.StartNew<ObservableCollection<DataGridEntity>>(curDataLoader.LoadValuesTask);
ItemsList = LoadValues.Result;
this.DataContext = ItemsList;

此代码段工作正常!但是使用.Result属性,UI线程会等待LoadValues任务返回。 所以我想这样做:

LoadValues = Task.Factory.StartNew<ObservableCollection<DataGridEntity>>(curDataLoader.LoadValuesTask);
LoadValues.ContinueWith((FinishLoadDataToDataGrid1) =>
{
   ItemsList = LoadValues.Result;
   this.DataContext = ItemsList;
});

差别很小。我使用ContinueWith来阻止UI线程等待。 但是,如果我这样做,他告诉我:“调用线程无法访问对象,因为不同的线程拥有它”在“this.DataContext = ItemsList;”

是时间问题吗?有没有人有任何想法?

2 个答案:

答案 0 :(得分:4)

您需要使用TaskScheduler.FromCurrentSynchronizationContext()在UI线程上运行ContinueWith。

LoadValues = Task.Factory.StartNew<ObservableCollection<DataGridEntity>>(curDataLoader.LoadValuesTask);
LoadValues.ContinueWith((FinishLoadDataToDataGrid1) =>
{
   ItemsList = LoadValues.Result;
   this.DataContext = ItemsList;
}, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());

答案 1 :(得分:2)

因为你正在使用UI线程,当你使用 ContinueWith 时,你的UI继续在UI线程上执行,新任务正在ThreadPool线程上执行,当新任务完成时,回调函数(通过)在ContinueWith中)将在ThreadPool线程上执行。 现在回调函数尝试访问UI线程拥有的对象,系统抛出错误。

通过在 TaskScheduler.FromCurrentSynchronizationContext()上安排回调函数,您可以指示系统在UI线程上执行此功能,一切正常。

这只是解释,因为D.Fihnn已经回答了你的问题。