在我调度新任务(Task.Factory.StartNew)的下面的代码中,它是冻结UI。任何人都可以帮我理解这里的错误。
public Task ShowHierarchy(IHierarchyFilterStrategy topHierarchyStrategy, IHierarchyFilterStrategy bottomHierarchyStrategy)
{
IEnumerable<IHierarchyNodeViewModel> topList = null;
IEnumerable<IHierarchyNodeViewModel> bottomList = null;
var context = TaskScheduler.FromCurrentSynchronizationContext();
var task = Task.Factory.StartNew(() =>
{
topList = topHierarchyStrategy != null ? topHierarchyStrategy.RetrieveHierarchy().ToList() : null;
bottomList = bottomHierarchyStrategy != null
? bottomHierarchyStrategy.RetrieveHierarchy().ToList()
: null;
});
return task.ContinueWith((antecedent) =>
{
View.SetAvailableNodes(topList, bottomList);
}, context);
}
编辑: 更具体一点......我的用户界面正在阻碍
topList = topHierarchyStrategy != null ? topHierarchyStrategy.RetrieveHierarchy().ToList() : null;
RetrieveHierarchy()方法是从缓存加载一些数据,如果不在缓存中,则转到DB获取数据。它与UI无关。
总结一下,我在这里做的是,我在第一个任务和第二个任务中从缓存/ DB获取两个列表,使用这两个值来更新UI(一些树节点)。但UI只有在尝试从第一行的RetrieveHierarchy()方法中检索值时才会冻结,而不是在其他地方。
问题仅在数据来自数据库时第一次出现。一旦将其加载到缓存中,此行/没有UI冻结的时间就没有了。
使用下面的行调用ShowHierarchy()方法
ShowHierarchy(topHierarchyStrategy,bottomHierarchyStrategy);
我没有在任何地方使用它的返回值。
答案 0 :(得分:2)
鉴于您发布的代码,我不能100%确定您的UI会锁定的原因。以下是尝试解决问题的一些建议/提示。
a)由于您使用的是Task
课程,因此您还应该可以访问async / await
个关键字。用async
标记你的方法,然后在里面你可以安全地等待任务完成。
类似的东西:
public async Task ShowHierarchy(IHierarchyFilterStrategy topHierarchyStrategy, IHierarchyFilterStrategy bottomHierarchyStrategy)
{
...
var topListTask = Task.Factory.StartNew(() =>
{
topHierarchyStrategy != null ? topHierarchyStrategy.RetrieveHierarchy().ToList() : null;
});
var bottomListTask = Task.Factory.StartNew(() =>
{
bottomList = bottomHierarchyStrategy != null
? bottomHierarchyStrategy.RetrieveHierarchy().ToList()
: null;
});
await Task.WhenAll(topListTask, bottomListTask);
//do things with topList, bottomList - they'll be ready at this point
}
b)在大多数情况下,使用TaskScheduler.FromCurrentSynchronizationContext()
模式时,您可以在不使用async / await
的情况下完成。
c)使用await
关键字时,您可以从任务中获得结果。您可以重新编写代码以等待每个列表(顶部和底部)的两个不同任务。它的好处是代码更简单,更容易调试。缺点是您没有并行执行任务,因此可能需要更长时间。值得一试 - 更简单的代码更容易调试。
答案 1 :(得分:0)
要解决此问题,我需要为LongRunning提供任务创建选项。这是更新的代码...
public Task ShowHierarchy(IHierarchyFilterStrategy topHierarchyStrategy, IHierarchyFilterStrategy bottomHierarchyStrategy)
{
IEnumerable<IHierarchyNodeViewModel> topList = null;
IEnumerable<IHierarchyNodeViewModel> bottomList = null;
var context = TaskScheduler.FromCurrentSynchronizationContext();
var options = TaskCreationOptions.LongRunning
| TaskCreationOptions.AttachedToParent;
var task = Task.Factory.StartNew(() =>
{
topList = topHierarchyStrategy != null ? topHierarchyStrategy.RetrieveHierarchy().ToList() : null;
bottomList = bottomHierarchyStrategy != null
? bottomHierarchyStrategy.RetrieveHierarchy().ToList()
: null;
},CancellationToken.None,options, TaskScheduler.Default);
return task.ContinueWith((antecedent) =>
{
View.SetAvailableNodes(topList, bottomList);
}, context);
}
此代码按预期工作,不会阻止UI。如果有人发现此代码有任何不常见/意外的情况,请告诉我。