如何把一个任务在C#4.0中睡觉(或延迟)?
在.NET 4.5中有Task.Delay
我怎样才能在.NET 4.0中做到这一点?
您可以使用Timer
在4.0中创build一个Delay
方法:
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; }
使用NuGet中的Microsoft.Bcl.Async包,它具有TaskEx.Delay
。
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; } }
从部分如何实现4.0中的Task.Delay
以下是可取消的Task.Delay实现的代码和示例代码。 您可能对Delay
方法感兴趣。
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; } } }
在许多情况下,纯粹的AutoResetEvent比Thread.Sleep()更好…
AutoResetEvent pause = new AutoResetEvent(false); Task timeout = Task.Factory.StartNew(()=>{ pause.WaitOne(1000, true); });
希望它有帮助
从这个答案扩展的想法:
new AutoResetEvent(false).WaitOne(1000);
您可以下载Visual StudioasynchronousCTP并使用TaskEx.Delay
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(); } }
这里有一个简洁的,基于计时器的实施与适当的清理:
var wait = new TaskCompletionSource<bool>(); using (new Timer(_ => wait.SetResult(false), null, delay, Timeout.Infinite)) await wait.Task;
要在.NET 4.0上使用此代码,您需要Microsoft.Bcl.Async NuGet包。