Using-blocks and asynchronous operations

Just as the community got used to using using...

I think that the using statement in C# is a really nice invention. It’s an excellent syntactic sugar for handling IDisposables in a correct fashion. I get the impression that it took a while for the community to make it part of their daily routine to use it and now, as we are coming there, there is a shift towards asynchronous programming that may render the using block useless (or at least temporarily so, I hope to see C# 5 handling this in conjunction with the await keyword).

Recently I ran into a situation where the asynchronous approach made the using block less ideal. I still like the simplicity of it, so I started thinking about creating a pattern that would only mean a minor shift away from it; an asynchronous using block. This pattern should ideally be close enough to a regular using block so that you could make some sort of (probably regex-based) search replace approach for moving to the asynchronous version.

This blog post is also written in a way so that it follows the thought process that I went through when making the code.

Executive summary

If you don’t want to wade through the whole thought process of creating the asynchronous using approach along with tests, skip ahead to the solution.

Let’s start from the beginning

As a starting point, let’s say that you a class that can save its contents to a Stream, and that you have some code doing that, nicely wrapped in a using block:

using (Stream stream = File.OpenWrite(@”\\slowserver\share\file.txt”))
{
    someClass.Save(stream);
}

...and then you figure that "nah, blocking this thread for that save... on that slow server… no thanks", and as it happens there is an asynchronous version of the method returning a Task:

using (Stream stream = File.OpenWrite(@”\\slowserver\share\file.txt”))
{
    // Disclaimer: in real code you would want to get hold of that Task, observing
    // any errors on it and handle them. This is omitted from the code samples for
    // the sake of focusing on the topic at hand.
    someClass.SaveAsync(stream);
}

And now you have a bug instead. You create a Stream, pass it to the asynchronous method and then immediately dispose the stream. When the save method comes around to writing to the Stream, it's is quite likely already disposed, and you will have an exception.

I imagined that rewriting the code to work with Task but without using blocks could look like this:

Stream stream = File.OpenWrite(@”\\slowserver\share\file.txt”);

someClass.SaveAsync(stream)
    .ContinueWith(task => 
    {
        if (stream != null)
        {
            stream.Dispose();
        }
    });

Simply put, this code consists of three things:

  1. Acquire the IDisposable resource
  2. Perform some action that uses that resource
  3. Dispose the resource

The goal was to encapsulate these steps into a reusable form.

Setting the stage

First I needed to figure out how to test this. The first test I wanted to write was one that used a regular using block, and that waited for the task to finish within the block. The reason was that this is a known and simple scenario where I knew the expected outcome.

[Test]
public void NormalUsingBlock_WaitForTask()
{
    var instance = new Disposable();
    using (instance)
    {
        Task.Factory.StartNew(() =>
        {
            if (instance.IsDisposed)
            {
                throw new ObjectDisposedException("The Disposable is already disposed.");
            }
        }).Wait();
    }
    Assert.IsTrue(instance.IsDisposed);
}

This is the bare minimum that I needed for the test: a class that implements IDisposable that contains a property indicating whether it’s disposed or not, and a task using that resource. If the resource is disposed before the tasks executes, an exception is thrown. Finally I verify that the resource has indeed become disposed.

The implementation of the Disposable class is the simplest possible:

public class Disposable : IDisposable
{
    public void Dispose()
    {
        IsDisposed = true;
    }

    public bool IsDisposed { get; private set; }
}

There, with that in place the first test passed as it should. Time for the next test. Now I wanted to create a scenario where the test consistently would fail if not waiting for the task within the using block; a test that would guarantee that the resource is disposed before the task tries to use it. This could probably be achieved by putting a Thread.Sleep inside the task, before checking the IsDisposed property, but Thread.Sleep is a thin ice to walk on. It can give you a reasonable chance that Dispose is invoked while sleeping, but there is no such guarantee. So I decided to use a wait handle instead, so that I can signal things in a deterministic way. I also decided to use an event to get notified when the object was disposed.

[Test]
public void NormalUsingBlock_AsyncFails()
{
    // arrange
    var instance = new Disposable();
    ManualResetEvent mre = new ManualResetEvent(false);
    EventHandler disposedHandler = (s, e) => mre.Set();
    instance.Disposed += disposedHandler;

    // act
    Task task;
    using (instance)
    {
        task = Task.Factory.StartNew(() =>
        {
            mre.WaitOne();
            if (instance.IsDisposed)
            {
                throw new ObjectDisposedException("The Disposable is already disposed.");
            }
        });
    }

    // assert
    Assert.Throws(() => task.Wait());

    // clean up
    instance.Disposed -= disposedHandler;
}

For this to work I needed to add the event code to the Disposable class, and raise the event when Dispose was invoked:

public class Disposable : IDisposable
{
    public event EventHandler Disposed;

    protected void OnDisposed(EventArgs e)
    {
        EventHandler handler = Disposed;
        if (handler != null) handler(this, e);
    }

    public void Dispose()
    {
        IsDisposed = true;
        OnDisposed(EventArgs.Empty);
    }

    public bool IsDisposed { get; private set; }
}

Now I was in a position where I could verify that a regular using block would dispose my resource as expected, and also that a regular using block could dispose my resource before the task was finished, if I didn’t wait for the task inside the block. Perfect, now I had the tools to create the asynchronous using functionality.

Making it work

I realized at this point that I would needed to write a few different tests to make sure things work as I wanted them to. I also realized setting up the tests will be quite similar for each test. Since I am not a huge fan of copy/pasting large portions of code that does the same thing, I decided to encapsulate the task creation into a method:

private static Task GetTask(Disposable disposable, WaitHandle waitHandle = null)
{
    return Task.Factory.StartNew(() =>
    {
        if (waitHandle != null)
        {
            // Wait for a signal. This enables us to wait in a deterministic
            // way before checking the disposed state.
            waitHandle.WaitOne();
        }

        if (disposable.IsDisposed)
        {
            throw new ObjectDisposedException("The Disposable is already disposed.");
        }
    });
}

There, now that I had a disposable resource and an asynchronous consumer, I could write a test for an asynchronous approach to using disposable resources.

As mentioned before, there are three steps involved; acquiring the disposable resource, invoking some code that uses the resource and finally disposing the resource. Disposing the resource is done in the exact same way regardless of what resource it is. This is also reflected by the regular using block; you as a developer never supply any code for that part. The other two however must be supplied by the developer.

With that in mind, I thought out the following approach:

[Test]
public void Using_WithTask()
{
    // act
    var task = Async.Using(() => new Disposable(),
        disposable => 
        {
            return GetTask(disposable);
        });
    task.Wait();

    // assert
    Assert.IsFalse(task.IsFaulted);
}

I imagined making an Async class (for functionality facilitating some async headaches), containing a Using method that takes two parameters; a Func that produces a disposable resource, and a Func taking such a resource as input and returning a task. Since I didn’t want to be forced to unnecessary type casting, I decided to make the method generic.

Do you see the similarity of this code construction, compared to the regular using block? First we have a statement that will produce an IDisposable object of some kind, then we have a code block where we can use that object, and in this case we call the variable holding the reference to that object disposable. We use it for whatever it’s needed for, and then we return a Task (so that we can chain ContinueWith calls on it, check the result, observe exceptions and so on).

By refactoring the code sample from above (that showed using a disposable resource with tasks, but without the help of any syntactic sugar or helper methods), I came to this implementation:

public static Task Using(
    Func disposableAcquisition, Func taskFunc)
    where T : IDisposable
{
    T instance = disposableAcquisition();

    return taskFunc(instance)
        .ContinueWith(task =>
        {
            if (!ReferenceEquals(instance, null))
            {
                instance.Dispose();
            }
            return task;
        });
}

…and the test passed! There it was, the first incarnation of the async using method.

My next step would be to create a version of the async using block for when I would want to execute any piece of code inside an asynchronous using block, but that where the code does not necessarily return a Task object. It could be that you just want to push some work off the UI thread to keep the UI responsive, for instance.

As always, test comes first. By now I realized that the structure of the following tests would be quite similar to the first one, in terms of necessary setups and such, so next step was to move some setup and teardown work to separate methods, moving some noise away from the tests:

[TestFixture]
public class AsyncTests
{
    private Disposable disposableInstance;
    private ManualResetEvent manualResetEvent;

    [SetUp]
    public void Setup()
    {
        disposableInstance = new Disposable();
        manualResetEvent = new ManualResetEvent(false);
        disposableInstance.Disposed += DisposedHandler;
    }

    private void DisposedHandler(object s, EventArgs e)
    {
        manualResetEvent.Set();
    }

    // the tests go here (removed for brevity)
}

Now the disposable class instance was created with all necessary wiring set up automatically before each tests was executed, so that code did not need to reside inside each test. I like how that makes the test code more focused on its purpose. So with that in place, I could make a simple test to make sure that I could execute code that does not involve a Task in the same sort of asynchronous manner:

[Test]
public void Using_WithAction()
{
    // act
    var task = Async.Using(() => disposableInstance,
        disposable =>
        {
            // wait for the wait handle to be signaled
            manualResetEvent.WaitOne();

            if (disposable.IsDisposed)
            {
                throw new ObjectDisposedException("The Disposable is already disposed.");
            }
        });

    manualResetEvent.Set();
    task.Wait();

    // assert
    Assert.IsFalse(task.IsFaulted);
}

Same approach as before, only this time without a Task. The code will throw an exception if the disposable object is disposed prior to the wait handle being signaled. The wait handle is signaled after the Async.Using method call returns. Finally the test verifies that the disposable resource is properly disposed, and that the resulting Task does not fail.

"Wait a minute..., didn't you just say that this test scenario did not involve any Task!?"  Yes I did, and I meant it ;-) The code that executes asynchronously within the block does not use or return any Task, but the construct itself, the Async.Using method, wraps the whole thing in a new Task that is returned so that your code can wait for it, chain other operations to follow on it, observe exceptions and so on. Let's looks at the implementation and it will be more clear:

public static Task Using(
    Func disposableAcquisition, Action action)
    where T : IDisposable
{
    T disposable = disposableAcquisition();

    return Task.Factory.StartNew(() => action(disposable))
        .ContinueWith(task =>
        {
            if (!ReferenceEquals(disposable, null))
            {
                disposable.Dispose();
            }
            return task;
        });
}

As you can see, it's very similar to the one we created first, but it creates a new Task that invokes the Action delegate that is passed into the method, and returns that Task object.

At this point, the Async class started to fulfill the needs that I had, so I didn't do much more work on it, but there are of course a lot more that code be done with it.

The final Async class

Here is the the "full" Async class, should you want to use it. I say "full", since it is in no way complete; there are many overloads that you could wish for, supporting Action and Func delegates with various number of type arguments, for instance.

You can also grab a full Visual Studio solution (containing both the class and some tests) from my BitBucket repository.

/*
 * This file is created by Fredrik Mörk, twitter.com/fmork
 *
 * It comes without any warranty of any kind. Use it at your own risk.
 * But feel free to do so.
 */

using System;
using System.Threading.Tasks;

namespace Alcedo.AsyncUsing
{
    /// 
    /// Contains functionality for asynchronous operations.
    /// 
    public static class Async
    {
        /// 
        /// Emulates a using block with asynchronous support.
        /// 
        /// A type that implements 
        /// A  that gets
        /// an object that implements .
        /// The action to perform asynchronously.
        public static Task Using(
            Func disposableAcquisition, Action action)
            where T : IDisposable
        {
            T disposable = disposableAcquisition();

            return Task.Factory.StartNew(() => action(disposable))
                .ContinueWith(task =>
                {
                    if (!ReferenceEquals(disposable, null))
                    {
                        disposable.Dispose();
                    }
                    return task;
                });
        }

        /// 
        /// Emulates a using block with asynchronous support.
        /// 
        /// A type that implements 
        /// A  that gets
        /// an object that implements .
        /// A  that
        /// uses the  object.
        /// 
        public static Task Using(
            Func disposableAcquisition, Func taskFunc)
            where T : IDisposable
        {
            T instance = disposableAcquisition();

            return taskFunc(instance)
                .ContinueWith(task =>
                {
                    if (!ReferenceEquals(instance, null))
                    {
                        instance.Dispose();
                    }
                    return task;
                });
        }

        /// 
        /// Emulates a using block with asynchronous support for a task that returns a result.
        /// 
        /// A type that implements 
        /// The type or the result produced by the task.
        /// A  that gets
        /// an object that implements .
        /// A  that uses
        /// the  object.
        public static Task Using(
            Func disposableAcquisition, Func> taskFunc)
            where T : IDisposable
        {
            T instance = disposableAcquisition();

            return taskFunc(instance)
                .ContinueWith(task =>
                {
                    if (!ReferenceEquals(instance, null))
                    {
                        instance.Dispose();
                    }
                    return task.Result;
                });
        }
    }
}