在下面的代码中,当我安排新任务(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);
}
编辑: 更具体地说...我的 UI 被阻止
topList = topHierarchyStrategy != null ? topHierarchyStrategy.RetrieveHierarchy().ToList() : null;
RetrieveHierarchy()方法是从缓存中加载一些数据,如果缓存中没有数据,然后去DB中获取数据。它与用户界面无关。
总而言之,我在这里所做的是,我在第一个任务和第二个任务中从缓存/数据库获取两个列表,使用这两个值来更新 UI(一些树节点)。但只有当 UI 尝试从第一行的 RetrieveHierarchy() 方法检索值时才会卡住,其他地方都不会卡住。
此问题仅在数据来自数据库时第一次出现。一旦加载到缓存中,该行就不会花费任何时间/UI 不会卡住。
使用下面的行调用 ShowHierarchy() 方法
显示层次结构(顶部层次结构策略,底部层次结构策略);
我没有在任何地方使用它的返回值。
最佳答案
鉴于您发布的代码,我不能 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) 在大多数情况下,当使用async/await
模式时,您可以不使用TaskScheduler.FromCurrentSynchronizationContext()
。
c) 使用 await
关键字时,您可以从任务中获取结果。您可以修改代码以等待每个列表(顶部和底部)的两个不同任务。这样做的好处是代码更简单,更容易调试。缺点是您没有并行执行任务,因此可能需要更长的时间。值得一试 - 更简单的代码更容易调试。
关于c# - Task.Factory.StartNew 卡住 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33341335/