How do I create a scheduler which never executes more than one Task at a time using async-await?

async-await, c#-4.0

Solution

There is a new `ConcurrentExclusiveSchedulerPair` type in .NET 4.5 (I don't remember if it was included in the Async CTP), and you can use its `ExclusiveScheduler` to restrict execution to one `Task` at a time.

Consider structuring your problem as a Dataflow. It's easy to just pass a `TaskScheduler` into the block options for the parts of the dataflow you want restricted.

If you don't want to (or can't) use Dataflow, you can do something similar yourself. Remember that in TAP, you always return started tasks, so you don't have the "creation" separated from the "scheduling" like you do in TPL.

You can use `ConcurrentExclusiveSchedulerPair` to schedule `Action`s (or `async` lambdas without return values) like this:

public static ConcurrentExclusiveSchedulerPair schedulerPair =
    new ConcurrentExclusiveSchedulerPair();
public static TaskFactory exclusiveTaskFactory =
    new TaskFactory(schedulerPair.ExclusiveScheduler);
...
public static Task RunExclusively(Action action)
{
  return exclusiveTaskFactory.StartNew(action);
}
public static Task RunExclusively(Func<Task> action)
{
  return exclusiveTaskFactory.StartNew(action).Unwrap();
}

There are a few things to note about this:

- A single instance of `ConcurrentExclusiveSchedulerPair` only coordinates `Task`s that are queued to its schedulers. A second instance of `ConcurrentExclusiveSchedulerPair` would be independent from the first, so you have to ensure the same instance is used in all parts of your system you want coordinated.

- An `async` method will - by default - resume on the same `TaskScheduler` that started it. So this means if one `async` method calls another `async` method, the "child" method will "inherit" the parent's `TaskScheduler`. Any `async` method may opt out of continuing on its `TaskScheduler` by using `ConfigureAwait(false)` (in that case, it continues directly on the thread pool).

Problem

I want to implement a class or pattern that ensures that I never execute more than one Task at a time for a certain set of operations (HTTP calls). The invocations of the Tasks can come from different threads at random times. I want to make use of the async-await pattern so that the caller can handle exceptions by wrapping the call in a try-catch. Here's an illustration of the intended flow of execution: Pseudo code from caller: ``` try { Task someTask = GetTask(); await SomeScheduler.ThrottledRun(someTask); } catch(Exception ex) { // Handle exception } ``` The `Task`class here might instead be an `Action` class depending on the solution. Note that I when I use the word "Schedule" in this question I'm not necessarily using it with relation to the .NET Task Scheduler. I don't know the async-await library well enough to know at what angle and with what tools to approach this problem. The TaskScheduler might be relevant here, and it may not. I've read the TAP pattern document and found patterns that almost solve this problem, but not quite (the chapter on interleaving).

Original source