How to implement a scatter-gather pattern in an ASP.NET web application?

354 Views Asked by At

Suppose an ASP.NET WebAPI request arrives at a controller method.

Suppose the request represents an 'event' which needs processed. The event has multiple operations associated with it that should be performed in parallel. For example, each operation may need to call out to a particular REST endpoint on other servers, which are I/O bound operations that should get started as soon as possible and should not wait for one to return before starting the next one.

What is the most correct/performant way to implement this pattern?

I've read that using Task.Run is a bad idea, because it just grabs additional ThreadPool threads, leaving the main request thread idle/blocked. While that makes sense if I was running a single task, I'm not sure that advice applies in this case.

For example, if the event has 4 operations that needed completed (each having possibly multiple I/O bound calls of their own), I would call Task.Run in a loop 4 times to initialize each operation, then wait on the resulting tasks with Task.WaitAll.

Q1: Would the main request thread be returned to the ThreadPool for use by another request while waiting for Task.WaitAll to return, or would it just hog the main thread leaving it idle until Task.WaitAll completes?

Q2: If it hogs the main thread, could that be resolved by marking the controller method with the async keyword, and using an await Task.WhenAll call instead? I'd imaging that this would return the main thread to the pool while waiting, allowing it to be used for other requests or event operations.

Q3: Since Task.Run queues up a work item that could be blocked on an I/O bound call, would performance improve if the operations were all implemented with async and used await calls on Task-based asynchronous I/O methods?

Regarding the whole approach of using Task.Run for the event's operations, the goal is just get all of the operation's I/O bound calls started as soon as possible. I suppose if (as in Q3) all operations were async methods, I could just get them all started on the main request thread in a loop, but I'm not sure that would be better than starting them with separate Task.Run calls. Maybe there's a completely different approach that I'm unaware of.

0

There are 0 best solutions below