I want to schedule a task to start in x ms and be able to cancel it before it starts (or just at the beginning of the task).
The first attempt would be something like
var _cancelationTokenSource = new CancellationTokenSource(); var token = _cancelationTokenSource.Token; Task.Factory.StartNew(() => { token.ThrowIfCancellationRequested(); Thread.Sleep(100); token.ThrowIfCancellationRequested(); }).ContinueWith(t => { token.ThrowIfCancellationRequested(); DoWork(); token.ThrowIfCancellationRequested(); }, token);
But I feel like there should be a better way, as this would use up a thread while in the sleep, during which it could be canceled.
What are my other options?
Task Delay means non-meeting of the preplanned due date of a task.
Some of these tasks are randomly delayed tasks. Note To create a randomly delayed task in Task Scheduler, click to select the Delay task for up to (random delay) check box, and then specify a time period from the drop-down menu. You use a time-based trigger to run these tasks at some scheduled times.
Delay(1000) doesn't block the thread, unlike Task. Delay(1000).
Like Damien_The_Unbeliever mentioned, the Async CTP includes Task.Delay
. Fortunately, we have Reflector:
public static class TaskEx { static readonly Task _sPreCompletedTask = GetCompletedTask(); static readonly Task _sPreCanceledTask = GetPreCanceledTask(); public static Task Delay(int dueTimeMs, CancellationToken cancellationToken) { if (dueTimeMs < -1) throw new ArgumentOutOfRangeException("dueTimeMs", "Invalid due time"); if (cancellationToken.IsCancellationRequested) return _sPreCanceledTask; if (dueTimeMs == 0) return _sPreCompletedTask; var tcs = new TaskCompletionSource<object>(); var ctr = new CancellationTokenRegistration(); var timer = new Timer(delegate(object self) { ctr.Dispose(); ((Timer)self).Dispose(); tcs.TrySetResult(null); }); if (cancellationToken.CanBeCanceled) ctr = cancellationToken.Register(delegate { timer.Dispose(); tcs.TrySetCanceled(); }); timer.Change(dueTimeMs, -1); return tcs.Task; } private static Task GetPreCanceledTask() { var source = new TaskCompletionSource<object>(); source.TrySetCanceled(); return source.Task; } private static Task GetCompletedTask() { var source = new TaskCompletionSource<object>(); source.TrySetResult(null); return source.Task; } }
Since .NET 4.5 has now been released, there's a very simple built-in way to delay a task: just use Task.Delay()
. behind the scenes, it uses the implementation that ohadsc decompiled.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With