At any time, I can receive a method call that will require a long-running operation to satisfy.

There are several of these methods. Because they share a resource, it's important that they don't run concurrently - each should run in sequence.

Normally, I'd simply make the calls in sequence:

var result1 = await Foo1Async();
var result2 = await Foo2Async();

However, in this case, the method calls to me are asynchronous:

void Bar1()
{
    var result = await Foo1Async();
    // ...
}

void Bar2()
{
    var result = await Foo2Async();
    // ...
}

I think I need to use Task.ContinueWith, and have come up with this:

readonly object syncLock = new Object();

private Task currentOperationTask = TaskUtilities.CompletedTask;
public Task<TResult> EnqueueOperation<TResult>(Func<Task<TResult>> continuationFunction)
{
    lock (this.syncLock)
    {
        var operation = this.currentOperationTask.ContinueWith(predecessor => continuationFunction()).Unwrap();
        this.currentOperationTask = operation;
        return operation;
    }
}

And I use it like this:

void Bar1()
{
    var result = await EnqueueOperation(() => Foo1Async());
    // ...
}

void Bar2()
{
    var result = await EnqueueOperation(() => Foo2Async());
    // ...
}

Is this the right way to approach this problem? Are there any pitfalls I should be aware of?

Edit
Report