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