c#tpl,继续出现问题“调用线程无法访问对象,因为不同的线程拥有它”
问题描述:
我正在运行Visual Studion 2010(Net 4.0) 我正在创建一个任务,将一些值加载到ObservableCollection中并返回之后的用户界面。这是代码:c#tpl,继续出现问题“调用线程无法访问对象,因为不同的线程拥有它”
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线程和新的任务执行是在线程池线程执行,当新的任务完成,然后回调函数(这是在传递ContinueWith)将在ThreadPool线程上执行。 现在,回调函数尝试访问UI线程拥有的对象,并且系统抛出错误。
通过调度TaskScheduler.FromCurrentSynchronizationContext()的回调函数,您可以指示系统在UI线程上执行此功能,并且一切正常。
这只是解释,因为D.Fihnn已经回答了您的问题。
完美!我不知道为什么,但它是帽子。谢谢! – manton 2012-02-02 15:36:24