There is Task.Delay in .NET 4.5
How can I do the same in .NET 4.0?
There is Task.Delay in .NET 4.5
How can I do the same in .NET 4.0?
You can use a Timer
to create a Delay
method in 4.0:
public static Task Delay(double milliseconds)
{
var tcs = new TaskCompletionSource<bool>();
System.Timers.Timer timer = new System.Timers.Timer();
timer.Elapsed+=(obj, args) =>
{
tcs.TrySetResult(true);
};
timer.Interval = milliseconds;
timer.AutoReset = false;
timer.Start();
return tcs.Task;
}
Callback()
definition use Dispatcher.BeginInvoke()
? –
Glen TrySetResult
would never get called. –
Carlist Timer
class specifically handles this internally to ensure that users of it don't need to hold onto a reference to it for it's lifetime. As long as the timer is currently running it adds a reference to itself from a rooted location and then removes it when it's no longer running. –
Catinacation timer
instances? Shouldn't they be disposed? –
Unwrap IDisposable
. It should always be disposed of explicitly unless there is specific documentation (e.g. as there is with Task
) that states otherwise. –
Pencil Use the Microsoft.Bcl.Async package from NuGet, it has TaskEx.Delay
.
You can use a Timer
to create a Delay
method in 4.0:
public static Task Delay(double milliseconds)
{
var tcs = new TaskCompletionSource<bool>();
System.Timers.Timer timer = new System.Timers.Timer();
timer.Elapsed+=(obj, args) =>
{
tcs.TrySetResult(true);
};
timer.Interval = milliseconds;
timer.AutoReset = false;
timer.Start();
return tcs.Task;
}
Callback()
definition use Dispatcher.BeginInvoke()
? –
Glen TrySetResult
would never get called. –
Carlist Timer
class specifically handles this internally to ensure that users of it don't need to hold onto a reference to it for it's lifetime. As long as the timer is currently running it adds a reference to itself from a rooted location and then removes it when it's no longer running. –
Catinacation timer
instances? Shouldn't they be disposed? –
Unwrap IDisposable
. It should always be disposed of explicitly unless there is specific documentation (e.g. as there is with Task
) that states otherwise. –
Pencil using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
Delay(2000).ContinueWith(_ => Console.WriteLine("Done"));
Console.Read();
}
static Task Delay(int milliseconds)
{
var tcs = new TaskCompletionSource<object>();
new Timer(_ => tcs.SetResult(null)).Change(milliseconds, -1);
return tcs.Task;
}
}
From the section How to implement Task.Delay in 4.0
object
that prints the value of it's ToString
method out. Note that he doesn't use that, nor any other non-library methods in his actual implementation, just the example function that tests it out. –
Catinacation Below is the code and sample harness for a cancellable Task.Delay implementation. You are likely interested in the Delay
method.:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DelayImplementation
{
class Program
{
static void Main(string[] args)
{
System.Threading.CancellationTokenSource tcs = new System.Threading.CancellationTokenSource();
int id = 1;
Console.WriteLine(string.Format("Starting new delay task {0}. This one will be cancelled.", id));
Task delayTask = Delay(8000, tcs.Token);
HandleTask(delayTask, id);
System.Threading.Thread.Sleep(2000);
tcs.Cancel();
id = 2;
System.Threading.CancellationTokenSource tcs2 = new System.Threading.CancellationTokenSource();
Console.WriteLine(string.Format("Starting delay task {0}. This one will NOT be cancelled.", id));
var delayTask2 = Delay(4000, tcs2.Token);
HandleTask(delayTask2, id);
System.Console.ReadLine();
}
private static void HandleTask(Task delayTask, int id)
{
delayTask.ContinueWith(p => Console.WriteLine(string.Format("Task {0} was cancelled.", id)), TaskContinuationOptions.OnlyOnCanceled);
delayTask.ContinueWith(p => Console.WriteLine(string.Format("Task {0} was completed.", id)), TaskContinuationOptions.OnlyOnRanToCompletion);
}
static Task Delay(int delayTime, System.Threading.CancellationToken token)
{
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
if (delayTime < 0) throw new ArgumentOutOfRangeException("Delay time cannot be under 0");
System.Threading.Timer timer = null;
timer = new System.Threading.Timer(p =>
{
timer.Dispose(); //stop the timer
tcs.TrySetResult(null); //timer expired, attempt to move task to the completed state.
}, null, delayTime, System.Threading.Timeout.Infinite);
token.Register(() =>
{
timer.Dispose(); //stop the timer
tcs.TrySetCanceled(); //attempt to mode task to canceled state
});
return tcs.Task;
}
}
}
Extending the idea from this answer:
new AutoResetEvent(false).WaitOne(1000);
You can download the Visual Studio Async CTP and use TaskEx.Delay
In many cases, a sheer AutoResetEvent is better than a Thread.Sleep()...
AutoResetEvent pause = new AutoResetEvent(false);
Task timeout = Task.Factory.StartNew(()=>{
pause.WaitOne(1000, true);
});
hope that it helps
public static void DelayExecute(double delay, Action actionToExecute)
{
if (actionToExecute != null)
{
var timer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(delay)
};
timer.Tick += (delegate
{
timer.Stop();
actionToExecute();
});
timer.Start();
}
}
Here's a succinct, timer-based implementation with proper cleanup:
var wait = new TaskCompletionSource<bool>();
using (new Timer(_ => wait.SetResult(false), null, delay, Timeout.Infinite))
await wait.Task;
To use this code on .NET 4.0, you need the Microsoft.Bcl.Async NuGet package.
await
keyword is part of the C# language, which is separate from the .NET Framework version. The problem is that Task<T>
does not have GetAwaiter
, which await
relies on. Microsoft.Bcl.Async supplies this. I updated my answer to mention the NuGet package. –
Carlist TaskEx.Delay
more succint, then? –
Irrational © 2022 - 2024 — McMap. All rights reserved.
Task.Delay()
does not put a task to sleep, it creates a newTask
. If you wait on that, then it will put a task to sleep for the given amount of time. Is that what you're looking for? ATask
that will complete after specified time? – CornedThread.Sleep
in synchronous code. – Hockett