Tuesday, July 19, 2011

Task Parallel Library: How To Write a Simple Delay Task

I just had a need for a delay task. A simple method that I can call to create a task that will turn a Func<T> into a Task<T> that will execute after a given delay.

The starting point for any Task creation based on an external asynchronous operation, like a Timer callback, is the TaskCompletionSource class.  It provides methods to transition the task it creates to different states. You call SetResult when the operation is completes, SetException if the operation fails, and SetCancelled if you want to cancel the task.

Here’s my RunDelayed method:

private static Task<T> RunDelayed<T>(int millisecondsDelay, Func<T> func)
{
    if (func == null)
    {
        throw new ArgumentNullException("func");
    }
    if (millisecondsDelay < 0)
    {
        throw new ArgumentOutOfRangeException("millisecondsDelay");
    }

    var taskCompletionSource = new TaskCompletionSource<T>();

    var timer = new Timer(self =>
    {
        ((Timer)self).Dispose();
        try
        {
            var result = func();
            taskCompletionSource.SetResult(result);
        }
        catch (Exception exception)
        {
            taskCompletionSource.SetException(exception);
        }
    });
    timer.Change(millisecondsDelay, millisecondsDelay);

    return taskCompletionSource.Task;
}


I simply create a new TaskCompletionSource and a Timer where the callback calls SetResult with the result of the given Func<T>. If the Func<T> throws, we simply catch the exception and call SetException. Finally we start the timer and return the Task.

You would use it like this:

var task = RunDelayed(1000, () => "Hello World!");
task.ContinueWith(t =>
{
    // 'Hello World' is output a second later on a threadpool thread.
    Console.WriteLine(t.Result);
});


Read more: Code rant
QR: task-parallel-library-how-to-write.html

Posted via email from Jasper-Net