c# .net multithreading parallel-processing task-parallel-library

¿Cómo poner una tarea a dormir(o demorar) en C#4.0?



.net multithreading (9)

A continuación se muestra el código y el arnés de muestra para una implementación de Task.Delay cancelable. Probablemente estés interesado en el método 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; } } }

Hay Task.Delay en .NET 4.5

¿Cómo puedo hacer lo mismo en .NET 4.0?


Aquí hay una implementación sucinta basada en temporizador con una limpieza adecuada:

var wait = new TaskCompletionSource<bool>(); using (new Timer(_ => wait.SetResult(false), null, delay, Timeout.Infinite)) await wait.Task;

Para usar este código en .NET 4.0, necesita el paquete Microsoft.Bcl.Async NuGet.


En muchos casos, un AutoResetEvent puro es mejor que un Thread.Sleep () ...

AutoResetEvent pause = new AutoResetEvent(false); Task timeout = Task.Factory.StartNew(()=>{ pause.WaitOne(1000, true); });

Espero que ayude


Extendiendo la idea de esta answer :

new AutoResetEvent(false).WaitOne(1000);



Puede usar un Timer para crear un método de Delay en 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; }



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(); } }


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

Desde la sección Cómo implementar Task.Delay en 4.0