如何在TaskScheduler.FromCurrentSychronizationContext的Continuation中使用Task.Result?

时间:2013-07-08 16:58:41

标签: c# wpf visual-studio-2010 mvvm .net-4.0

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

//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上的构建错误,但是当它不存在构建错误时。问题是我得到了一个反应迟钝的用户界面。

我做错了什么?

1 个答案:

答案 0 :(得分:3)

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

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

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

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

来自MSDN

  

<强> TaskCreationOptions.LongRunning
  指定任务将是a   长期,粗粒度的操作涉及更少,更大   组件比细粒度系统。它提供了一个提示   任何超额认购的TaskScheduler可能是有保证的。超额认购   允许您创建比可用硬件数更多的线程   线程。

因此,您可以将任务创建更改为:

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