Reputation: 6461
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
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
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
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