C# TPL,问题与继续"Calling thread cannot access object because different thread owns it"



我正在运行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;"

这是时间问题吗?有人有什么想法吗?

您需要使用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());

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

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

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

相关内容

最新更新