【问题标题】:C# .NET Core async methods in controller控制器中的 C# .NET Core 异步方法
【发布时间】:2022-06-14 10:06:21
【问题描述】:

我对 .NET Core 比较陌生,并试图了解异步/等待的使用,以帮助加快加载缓慢的页面。

我原来的控制器方法是这样的:

public IActionResult Index()
{
      //other code here

      regionVM.listEvents = getEvents(regionCatID);
      regionVM.listNews = getNews(regionCatID);
      regionVM.listLIA = getLIA(regionCatID);
      regionVM.listAwards = getAwards(regionCatID);

      return View("/Views/Regions/Index.cshtml", regionVM);
}

getEvents、getNews、getLIA 和 getAwards 是同一控制器中的所有其他方法。它们在视图模型中填充的相应列表用于在视图中显示四个不同的区域。这一切都正确填充,但速度很慢。

我阅读了很多不同的文章和帖子,但特别尝试更新我的代码:How can I run both of these methods 'at the same time' in .NET 4.5?

我的新方法如下所示:

public async Task<IActionResult> Index()
{
      //other code here

      var eTask = Task.Run(() => getEvents(regionCatID));
      var nTask = Task.Run(() => getNews(regionCatID));
      var lTask = Task.Run(() => getLIA(regionCatID));
      var aTask = Task.Run(() => getAwards(regionCatID));

      regionVM.listEvents = await eTask;
      regionVM.listNews = await nTask;
      regionVM.listLIA = await lTask;
      regionVM.listAwards = await aTask;

      return View("/Views/Regions/Index.cshtml", regionVM);
}

这似乎工作和编译没有任何错误,但现在当区域页面加载时,这四个区域是否实际填充在视图中是有点命中或错过的。例如,有时新闻区域会是空白的,当我知道有新闻项目应该被填充并且正在使用旧的同步方法填充时。

是否在任务执行完成之前加载视图?或者我会以完全错误的方式解决这个问题?感谢您的任何建议。

【问题讨论】:

  • 您应该至少包含其中一种方法的代码。有人可以帮助您优化数据调用。
  • .net 4.5 是旧的 .net 框架。该线程中的建议与此处无关。 (MS 的术语令人困惑,但 ASP.NET != .net4.x)你不需要线程,所以删除 task.run() 东西。您的应用程序池/服务器将处理线程。 Async/Await 不是线程,而是对线程的非阻塞调用。最好始终保持异步,因此也使所有这些方法异步。如果速度是一个问题,通常是由于将大型数据集返回到视图......如果是这种情况,请考虑分页。
  • 根据您的描述,我想提出另一种想法,即在您的视图中使用 Ajax 查询分别调用您的 4 个方法。如您所知,Ajax 查询是异步的,因此您可以编写方法来调用它们。它可能会使您的网站表现得像新闻部分会先加载,而奖项部分可能会最后加载,但最终会加载所有内容,除非发生一些异常,然后不会加载有问题的部分。我同意@pcalkins 的观点,“通常是由于将大型数据集返回到视图”
  • 你也可以看看this document...
  • 顺便说一句,在asp.net core中,我们有async方法,然后我们在调用async方法时使用await。

标签: c# asp.net-core asynchronous async-await asp.net-core-mvc


【解决方案1】:

有不同的方法来处理这个问题,但首先,我会确保理解 async/await。 Microsoft 有关于该主题的精彩文章和视频。

另外,我不知道您调用的方法(例如 getEvents)是什么样的,所以我的回答是假设它们是真正的异步方法。

一般来说,我会避免在 ASP.NET Core 应用程序中使用 Task.Run。它只会导致额外的不必要的线程池调度。

    // Your new code can easily be rewritten as:
    public async Task<IActionResult> Index()
    {
          //other code here
          
          regionVM.listEvents = await getEvents(regionCatID);
          regionVM.listNews = await getNews(regionCatID);
          regionVM.listLIA = await getLIA(regionCatID);
          regionVM.listAwards = await getAwards(regionCatID);

          return View("/Views/Regions/Index.cshtml", regionVM);
    }

    // OR
    public async Task<IActionResult> Index()
    {
          //other code here
          
          var task1 = getEvents(regionCatID);
          var task2 = getNews(regionCatID);
          var task3 = getLIA(regionCatID);
          var task4 = getAwards(regionCatID);
       
          await Task.WhenAll(task1, task2, task3, task4);

          regionVM.listEvents = await task1;
          regionVM.listNews = await task2;
          regionVM.listLIA = await task3;
          regionVM.listAwards = await task4;

          return View("/Views/Regions/Index.cshtml", regionVM);
    }

因为每个示例中的代码都是等待的,所以它保证在渲染区域页面时,将填充四个区域,因为该行

return View("/Views/Regions/Index.cshtml", regionVM);

所有数据已被提取后执行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-11
    相关资源
    最近更新 更多