Allow async method to be called only one instance at a time

I would consider altering the method body of CallSlowStuff to post messages to a TPL DataFlow ActionBlock, and configuring it to a single degree of parallelism:

So keep a single ActionBlock somewhere:

ActionBlock actionBlock = 
    new ActionBlock<object>(
         (Func<object,Task>)CallActualSlowStuff,
         new ExecutionDataflowBlockOptions(){MaxDegreeOfParallelism=1});

Now:

public void CallSlowStuff()
{
    actionBlock.Post(null);
}

private async Task CallActualSlowStuff(object _)
{
    using (File.Open("_", FileMode.Create, FileAccess.Write, FileShare.None)) {
        for (int i = 0; i < 10; i++) {
            await Task.Factory.StartNew(Console.WriteLine, i);
            await Task.Delay(100);
        }
    }
}

You need some sort of async lock. Stephen Toub has a whole series of articles about building async synchronization primitives (including AsyncLock). A version of AsyncLock is also contained in Stephen Cleary's AsyncEx library.

But probably a simpler solution would be to use the built-in SemaphoreSlim, which does support asynchronous waiting:

private static SemaphoreSlim SlowStuffSemaphore = new SemaphoreSlim(1, 1);

private static async void CallSlowStuff () {
    await SlowStuffSemaphore.WaitAsync();
    try {
        await DoSlowStuff();
        Console.WriteLine("Done!");
    }
    catch (Exception e) {
        Console.WriteLine(e.Message);
    }
    finally {
        SlowStuffSemaphore.Release();
    }
}