2013-07-08 27 views
0

在WPF应用程序中,我有一个按钮绑定到我的视图模型中的Command。该命令启动任务以从数据库获取信息,然后更新一些属性。如何在TaskScheduler.FromCurrentSychronizationContext中继续使用Task.Result?

//list in vm to be bound to.. 
List<DataModel.Item> BoundList; 
//new command() => 
{ 
    var t = Task.Factory.StartNew<IEnumerable<DataModel.Item>>(() => 
     return datasvc.GetItems(); 
    ); 
    t.ContinueWith(t2 => { 
     BoundList = t.Result; 
    }, TaskScheduler.FromCurrentSychronizationContext); 
} 

该项目上t.Result报告生成错误,当我使用FromCurrentSynchronizationContext标志,但是当它不存在没有生成错误。问题是我得到一个没有响应的用户界面。

我在做什么不正确?

+0

你什么错误? – SLaks

+0

调用'Task.Run()'。或者让它实际上是异步的,以便完全避免后台线程。 – SLaks

+0

我不能在这个项目中使用.NET 4.5,所以Asych/Await的东西不适用于我。 –

回答

3

这不是一个标志,它是一种静态方法。此外,T2是任务的结果,所以你不需要原始任务存储为一个单独的变量:

Task.Factory.StartNew(datasvc.GetItems) 
    .ContinueWith( 
     t => 
     { 
      BoundList = t.Result; 
     }, TaskScheduler.FromCurrentSychronizationContext()); 

如果你Task对象是在UI线程中运行(因此它冻结),这可能是因为您已经在线程池中运行了多个线程。默认情况下,Task将在ThreadPool线程上运行,除非它们全部被使用。

但是,您可以通知.NET它是一个长时间运行的操作,并且它通常会生成其他线程来阻止您的UI冻结。

MSDN

TaskCreationOptions.LongRunning
指定一个任务将是涉及比细粒度的系统更少,更大的 组件 长期运行,粗粒度操作。它向 TaskScheduler提供了可能需要超额认购的提示。超额预订 可让您创建比可用数量的硬件线程更多的线程。

所以,你会改变你的任务创建到:

Task.Factory.StartNew(datasvc.GetItems, TaskCreationOptions.LongRunning) 
+0

这样做。现在它编译,但我仍然得到一个冻结的UI :(回到绘图板 –

+0

@MikeCaron't.Result'返回多少项?如果它返回了大量的项目,并且BoundList绑定到UI ,这可能会使界面冻结 – PoweredByOrange

+1

@MikeCaron我加入到我的答案,希望能解决这个问题 –