我正在运行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;”
是时间问题吗?有没有人有任何想法?
答案 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已经回答了你的问题。