Luis Agudo
Luis Agudo

Reputation: 81

Launching parallel Tasks on an asp.NET Core MVC web

I've an ASP.NET Core MVC website with a d3.js map. I need to run a serie of async methods in the background to capture some data, treat it, and send it to the map.

I've created a class with this methods, and one "entry point" who controlls the launching of the rest of the Tasks. This "entry point" is called from the HomeController.cs, before the view loads. But I really don't care if the view loads after or before the parallel tasks start doing their thing

The Code of the HomeController is:

 //public IActionResult PulseNest()
        public async Task<ActionResult> PulseNest()
        {
            ViewData["Title"] = "PulseNest";
            Listener nl = new Listener();
            nl.startListening();
            return View();
        }

The code of the Listener is:

 public async void startListening()
 {            
    listen([...]);
    drawing();            
 }

[...]

private async Task drawing()
{
  do
  {
    if (pool.Count > 0)
    {
      //This is the call for the SignalR sending data to the front
      await uH.SendNewPoint(pool[rdm.Next(0, pool.Count - 1)]);
    }
  } while (true);
}

[...]

 private async Task listen([...])
{
     //[Retrieving Data]
     processData([...]);

 }
[...]

 private void processData([...])
{
    //[Processing the data and adding it to the pool]
}

What I intended to do is: when I access this page I launch a series of threads that retrieve and treat data (for now if I can make it work only one I would be really happy), and another one who send this data to the front end with SignalR, and then represent this data on the map.

The catastrophic result is: when I access this page the HomeController calls to the startListening. Then startListening calls to listen and drawing and the execution keep looping in there... Threads are not working at all... And never returns to the HomeCotroller, and therefore View() is never called...

I even tried to define startListening() as Task, and call it from HomeController like this:

            Listener nl = new Listener();
            Task listening = nl.startListening();
            listening.Start();
            return View();

But then the code throws an exception: InvalidOperationException: Start may not be called on a task that has completed.

I've also tried to do this in the Listen class:

        public async Task startListening()
        {            
            Task listening = listen([...]);
            listening.Start();
            Task draw = drawing();
            draw.Start();
        }

In this case, when I debug the program the view loads, but I can see in the Events of the Diagnostic Tools that some thread is throwing the exception: "System.InvalidOperationException in System.Provate.CoreLib.dll("Start may not be called on a promise-style task."). If I double click on it, it's refering to the listening.Start(); line...

I'm pretty new in Core and I'm pretty sure that this is a fault in my understanding of Task. But I've searched in the MSDN and I can't find an easy explanation of this for Core MVC.

Any help, or reference to an MSDN article, would be very appreciated.

Upvotes: 0

Views: 1013

Answers (1)

Tao Zhu
Tao Zhu

Reputation: 779

You have an infinite loop inside drawing(), it blocks your executing thread. You can use Task.Run to run your long time task in other thread. But in your scenario, you can use a HostedService to run your infinite task: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.2

Upvotes: 2

Related Questions