Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run method on a separate thread inside Action

Suppose I have an Action like below that I want to return the View asap and continue doing some work in the background thread.

public async Task<ActionResult> Index()
{
    Debug.WriteLine("Inside Index");

    var newCustomer = new Customer
    {
        Name = "Ibrahim"
    };

    Task.Run(() => SaveCustomer(newCustomer));

    Debug.WriteLine("Exiting Index");

    return View();
}

private async Task SaveCustomer(Customer NewCustomer)
{
    Debug.WriteLine("Started Saving Customer");

    await Task.Delay(2000);

    Debug.WriteLine("Completed Saving Customer");
}

I do get the output as intended which is:

Inside Index
Exiting Index
Started Saving Customer
Completed Saving Customer

But what bothers me is that I get a warning that my Index action will run synchronously regardless and I should put an await but then the view is returned after SaveCustomer is completed and the purpose is defeated.

How am I doing this wrong? Any suggestion is appreciated.

like image 693
lbrahim Avatar asked Jan 18 '26 04:01

lbrahim


1 Answers

But what bothers me is that I get a warning that my Index action will run synchronously

How am I doing this wrong?

Don't force asynchrony from the top down. Instead, start with naturally-asynchronous operations at the lowest level (e.g., EF6 database access), and allow the asynchrony grow from the lowest-level code upward.

Also, on ASP.NET, you should strongly avoid Task.Run.

Applying these two principles results in an Index method like this:

public async Task<ActionResult> Index()
{
  Debug.WriteLine("Inside Index");

  var newCustomer = new Customer
  {
    Name = "Ibrahim"
  };

  await SaveCustomer(newCustomer);

  Debug.WriteLine("Exiting Index");

  return View();
}

but then the view is returned after SaveCustomer is completed and the purpose is defeated.

Not at all. The purpose of asynchronous ASP.NET code is not to return early to the client. async and await do not change the HTTP protocol. await on the server side yields to the thread pool, not the client.

If you need to return early (and most people don't - they only think they "need" to), then you should use one of the established patterns for returning early (as I describe on my blog). Note that the only proper (i.e., fully reliable) solution entails setting up a reliable queue with an independent background process.

like image 69
Stephen Cleary Avatar answered Jan 20 '26 20:01

Stephen Cleary