简体   繁体   中英

C# .NET Core async methods in controller

I'm relatively new to .NET Core and trying to get my head around async/await usage to help speed up a slow-loading page.

My original controller method looked like this:

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, and getAwards are all other methods within the same controller. The corresponding lists they populate in the view model are used to display four different areas in the view. This all populates properly, but is slow.

I read a lot of different articles and posts, but tried to update my code following this one in particular: How can I run both of these methods 'at the same time' in .NET 4.5?

My new method looked like this:

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);
}

This seemed to work and compiled without any errors, but now when the regions pages load it's sort of hit or miss whether the four areas actually populate in the view. For instance, sometimes the news area will be blank, when I know there are news items that should be populated and were populating with the old synchronous method.

Is the view loading before the tasks are done executing? Or am I going about this completely the wrong way? Thanks for any suggestions.

There are different ways to handle this, but firstly, I would make sure to understand async/await. Microsoft has great articles and videos on the topic.

Also, I have no idea what the methods you are calling (eg getEvents) look like so my answer is assuming they are true async methods.

I would avoid Task.Run within ASP.NET Core apps generally speaking. It only results in extra unnecessary Thread Pool scheduling.

 // 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); }

Because the code in each of these examples is awaited, its guaranteed the when the regions page is rendered, the four areas will be populated because the line

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

Is only executed once all the data has already been fetched.


There are others ways to also improve page performance if you want it to be rendered quickly. For example , I'm not sure how much data is actually being fetched in your controller action, however, instead of only loading the page when all the data is returned, you can use ajax calls to fetch all this data. This way, your controller 'Index' action wont fetch all the data and your page will render immediately, then you make ajax calls from your javascript code to get data for each area.

A common example for doing this is something like a Dashboard page.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM