4

I have a method similar to the following in WebAPI - MVC

public IActionResult Post(Model model)
{
      ALongRunningMethod();
      return Ok();
}

I have two options.

  1. Wait for the method to complete. But, what if its too long ? Doesn't the API timeout ?
  2. Run that in a separate thread using Tasks but return Ok (200 HTTP Code) immediately ? What if some exception occur in that long running method ?

Totally confused. What should I do in this case ?

  • There are a _lot_ of questions on SO on how to run long-running tasks in ASP.NET. Sharing your research will help us narrow down the best answer; "totally confused" does not. I understand your question is about when and what to return, but you won't have that problem if you do background tasks the proper way. – CodeCaster Sep 22 '14 at 10:32
  • Immediate return from the action is not the goal here and that's not what async is about. It's rather about not blocking the Web Api in case of time-consuming calls and delegating them to a background thread, so Web Api can take another request. You still should wait till operation completes and return real status :-) – Mariusz Jun 16 '15 at 08:56

3 Answers3

5

Starting from .Net 4.5.2, you now have QueueBackgroundWorkItem to deal with long running operations in ASP.Net.

Andreas Schwarz
  • 1,788
  • 17
  • 42
ken2k
  • 48,145
  • 10
  • 116
  • 176
3

This is a common issue in web applications. I would create a GUID, pass it into a task, run the task, pass back the GUID. In the mean time, the task will continue. If you have a database you could save the GUID to the DB from the task, indicating some status. e.g. You could have a database table called 'Task' with columns TaskID and Status.

Then you can use the GUID to retrieve (poll) for the status of the task at regular intervals.

The commenter is correct in saying that long-running tasks in ASP.NET is a dangerous game because you have no control over the lifetime of the app domain.

krisdyson
  • 3,217
  • 7
  • 43
  • 86
  • 2
    Doesn't WEB API work on the assumption that it can tear down and kill processes once no requests are running? This would mean that there would be no guarantee that your process would ever finish. – BenjaminPaul Sep 22 '14 at 10:16
  • This is true, however, the underlying pattern is useful – krisdyson Sep 22 '14 at 10:54
  • If you are lazy or don't care about the code completing perhaps. – BenjaminPaul Sep 22 '14 at 10:55
  • The underlying pattern is to invoke an async op passing in a unique token and then polling for the status. Laziness doesn't come into it. – krisdyson Sep 22 '14 at 10:57
  • What happens if there is an exception? Or if the app domain is stopped? I agree with creating an ID and returning it so that you can poll for status... however running the process from the web api controller is not the right way of handling this. – BenjaminPaul Sep 22 '14 at 11:00
  • OK, I'm talking about the underlying pattern. You're right about the pitfalls of the concrete solution suggested; however, whether that in itself makes the suggestion invalid depends on the nature of the async op. When I refer to the underlying pattern, this means the async op could be launched in a windows service or azure worker role etc. – krisdyson Sep 22 '14 at 11:03
  • 1
    @BenjaminPaul I have acknowledged your point in the answer. – krisdyson Sep 22 '14 at 11:06
2

The best way to handle this would be to have a separate service to actually perform the tasks that you want to run as opposed to running them from within your web api controllers.

Have the Web API endpoint write an entry to the database requesting some work to be done and have another separate service read from that table and perform those long running tasks.

You can of course provide some kind of id so that you can query for progress using another end point within your WEB API if you so wish.

The reason for this and the problem you are likely going to run into is that ASP.NET only knows about code running that is associated with a request, the code you are looking to run in a background thread would not be seen as part of a request could therefore be ended at any point for a number of reaons...

Here are some examples of those risks:

  1. An unhandled exception in a thread not associated with a request will take down the process.
  2. If you run your site in a Web Farm, you could end up with multiple instances of your app that all attempt to run the same task at the same time.
  3. The AppDomain your site runs in can go down for a number of reasons and take down your background task with it. This could corrupt data if it happens in the middle of your code execution.

See this page for more information: http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx/

Hope this helps.

BenjaminPaul
  • 2,931
  • 19
  • 18