ventajas tener temprana startnew sobre sexualidad sexuales run relaciones reflexion recomendaciones razones parallel para multiple library las for example evitar ejercicio edad desventajas contra como async argumentos adolescencia c# .net task-parallel-library

tener - task.factory.startnew example c#



Manera correcta de retrasar el inicio de una tarea. (6)

Quiero programar una tarea para comenzar en x ms y poder cancelarla antes de que comience (o solo al comienzo de la tarea).

El primer intento sería algo así como

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

Pero siento que debería haber una mejor manera, ya que esto usaría un hilo mientras está en el sueño, durante el cual podría cancelarse.

¿Cuáles son mis otras opciones?


Como mencionó Damien_The_Unbeliever , el CTP Task.Delay incluye Task.Delay . Afortunadamente, tenemos 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; } }


Desde que se lanzó .NET 4.5, existe una forma muy simple de retrasar una tarea: simplemente use Task.Delay() . Detrás del escenario, utiliza la implementación que ohadsc descompiló .


La respuesta correcta en el futuro probablemente será Task.Delay . Sin embargo, actualmente solo está disponible a través del CTP asíncrono (y en el CTP, está en TaskEx en lugar de Task).

Desafortunadamente, debido a que solo está en CTP, tampoco hay muchos enlaces buenos para la documentación.



No he probado esto, pero aquí hay un primer paso en los métodos de envoltura para crear una tarea de ''Retardo'' inicial o para continuar después de un Retraso. Si encuentra problemas, siéntase libre de corregir.

public static Task StartDelayTask(int delay, CancellationToken token) { var source = new TaskCompletionSource<Object>(); Timer timer = null; timer = new Timer(s => { source.TrySetResult(null); timer.Dispose(); }, null, delay, -1); token.Register(() => source.TrySetCanceled()); return source.Task; } public static Task ContinueAfterDelay (this Task task, int delay, Action<Task> continuation, CancellationToken token) { var source = new TaskCompletionSource<Object>(); Timer timer = null; var startTimer = new Action<Task>(t => { timer = new Timer(s => { source.TrySetResult(null); timer.Dispose(); },null,delay,-1); }); task.ContinueWith (startTimer, token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Current); token.Register(() => source.TrySetCanceled()); return source.Task.ContinueWith(continuation, token); }


Puede usar el método de sobrecarga Token.WaitHandle.WaitOne (int32 milisegundos) para especificar el número de milisegundos que debe esperar su tarea. Pero la diferencia clave entre Thread.Sleep (xxx) y Token.WaitHandle.WaitOne (xxx) que luego bloquea los subprocesos hasta que transcurra el tiempo especificado o se haya cancelado el token.

Aquí hay un ejemplo

void Main() { var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; var task = Task.Factory.StartNew(() => { // wait for 5 seconds or user hit Enter key cancel the task token.WaitHandle.WaitOne(5000); token.ThrowIfCancellationRequested(); Console.WriteLine("Task started its work"); }); Console.WriteLine("Press ''Enter'' key to cancel your task"); Console.Read(); tokenSource.Cancel(); }