c# - Task.Factory.StartNew 卡住 UI

标签 c# asynchronous task-parallel-library task

在下面的代码中,当我安排新任务(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/

相关文章:

c# - Web App Bot 不包含 C# 的 LUIS 模板

c# Mysql 已经有一个与此 Connection 关联的打开的 DataReader

c++ - C++ 编译器如何在 std::async 的延迟执行和异步执行之间进行选择?

c# - Task.WhenAll - 何时使用它

c# - Azure:无法执行套接字上的操作,因为系统缺乏足够的缓冲区空间或队列已满

python - 当Python Bottle准备好文件时,如何实现自动更新的 “Your file is being prepared. Please wait 1 minute.”?

java - 如何在使用 Spring 返回响应后调用异步 Controller 逻辑?

asynchronous - 从 Azure 表结构读取 N 个实体的最有效方法是什么

c# - 无法将 TransactionScope 与任务一起使用

c# - .NET 中的惰性正则表达式匹配。这里出了什么问题?