Reputation: 350
I have an ASP.NET Core 5 API that needs to do some background tasks. These background tasks will run for the entirety of the applications life, and will be reading azure queues so spending a lot of time sitting doing nothing.
I have read that for I/O you shouldn't use Task.Run() as it's inefficient, but if in my case I'm not waiting on an I/O call, I'm waiting on a background task that happens to do a lot of I/O calls, is that ok? It seems if I don't use Task.Run() then every time my background task gets something from the queue and so the code after await continues, then it will be blocking some main thread in ASP that spooled up the task in the first place.
Upvotes: 0
Views: 3547
Reputation: 457302
These background tasks will run for the entirety of the applications life, and will be reading azure queues so spending a lot of time sitting doing nothing.
I agree with others' comments: by far the best solution is to move these out of the ASP.NET process completely. Azure Functions, for example, has built-in support for Azure Storage Queues. Benefits of Azure Functions over ASP.NET in-process include:
I have read that for I/O you shouldn't use Task.Run() as it's inefficient
Task.Run
should be avoided in ASP.NET's request processing pipeline. It's always inefficient regardless of the type of work being done.
Task.Run
can be useful for background tasks in an ASP.NET process, in particular if there's blocking work done during startup of the background task.
The main thing with Task.Run
on ASP.NET is that you don't want to interfere with the ASP.NET thread pool heuristics. Regularly queueing work to the thread pool is a problem, since you're stealing threads and then re-injecting them on a regular basis. So using Task.Run
when processing each HTTP request or when processing each queue item would be a bad idea. A single Task.Run
done once at startup doesn't matter.
It seems if I don't use Task.Run() then every time my background task gets something from the queue and so the code after await continues, then it will be blocking some main thread in ASP that spooled up the task in the first place.
This is a valid concern if there's blocking work being done during your message processing.
One way to think about async
/await
is that each method is broken up into pieces (at each await
point), and each of those pieces is scheduled separately, one at a time. Each time a piece is scheduled, it takes a thread pool thread, runs the piece, and then returns the thread. As long as the work is fast, this is fine, but if one of those pieces has blocking work, then the ASP.NET thread pool heuristics can be impacted.
Upvotes: 3
Reputation: 4187
Checkout Background tasks with hosted services in ASP.NET Core to see how do do this in a separate process. That may be your best bet. You also use background processes within a web application if you want. Within the background task, use the synchronous API to do your I/O and use await.
Upvotes: 1