Slaggg
Slaggg

Reputation: 6461

How to Schedule a task for future execution in Task Parallel Library

Is there a way to schedule a Task for execution in the future using the Task Parallel Library?

I realize I could do this with pre-.NET4 methods such as System.Threading.Timer ... however if there is a TPL way to do this I'd rather stay within the design of the framework. I am not able to find one however.

Thank you.

Upvotes: 12

Views: 5718

Answers (3)

Glenn Slayden
Glenn Slayden

Reputation: 18749

This feature was introduced in the Async CTP, which has now been rolled into .NET 4.5. Doing it as follows does not block the thread, but returns a Task which will execute in the future.

Task<MyType> new_task = Task.Delay(TimeSpan.FromMinutes(5))
                            .ContinueWith<MyType>( /*...*/ );

(If using the old Async releases, use the static class TaskEx instead of Task)

Upvotes: 22

Mike Hadlow
Mike Hadlow

Reputation: 9517

You can write your own RunDelayed function. This takes a delay and a function to run after the delay completes.

    public 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;
    }

Use it like this:

    public void UseRunDelayed()
    {
        var task = RunDelayed(500, () => "Hello");
        task.ContinueWith(t => Console.WriteLine(t.Result));
    }

Upvotes: 11

Jim Mischel
Jim Mischel

Reputation: 133975

Set a one-shot timer that, when fired, starts the task. For example, the code below will wait five minutes before starting the task.

TimeSpan TimeToWait = TimeSpan.FromMinutes(5);
Timer t = new Timer((s) =>
    {
        // start the task here
    }, null, TimeToWait, TimeSpan.FromMilliseconds(-1));

The TimeSpan.FromMilliseconds(-1) makes the timer a one-shot rather than a periodic timer.

Upvotes: 2

Related Questions