2010-11-19 7 views
12

¿Existe alguna manera de programar una tarea para su ejecución en el futuro utilizando la Biblioteca de tarea paralela?Cómo programar una tarea para su futura ejecución en la Tarea Biblioteca paralela

Me doy cuenta de que podría hacer esto con los métodos pre-.NET4 como System.Threading.Timer ... sin embargo, si hay una forma TPL para hacer esto prefiero mantenerme dentro del diseño del framework. No puedo encontrar uno sin embargo.

Gracias.

Respuesta

2

Establezca un temporizador de un disparo que, cuando se dispara, inicia la tarea. Por ejemplo, el siguiente código esperará cinco minutos antes de comenzar la tarea.

TimeSpan TimeToWait = TimeSpan.FromMinutes(5); 
Timer t = new Timer((s) => 
    { 
     // start the task here 
    }, null, TimeToWait, TimeSpan.FromMilliseconds(-1)); 

El TimeSpan.FromMilliseconds(-1) hace que el temporizador de un one-shot en lugar de un temporizador periódico.

+0

funciona eso? Parece que el temporizador podría recibir GCd después de que se saliera del alcance, y antes de que mi evento se dispare ... En cualquier caso, esperaba algo nativo para TPL (por ejemplo, tomar una tarea como argumento y permitir el mapeo de tareas), que no parece existir. – Slaggg

+0

Sí, en ese ejemplo el temporizador podría ser recolectado. Declare la referencia del temporizador en un ámbito que evitará la recopilación prematura. –

+0

OK - gracias por su respuesta. Mencioné en la pregunta que un temporizador funcionaría; Esperaba algo que tratara con objetos Task de forma nativa. ¡Gracias de cualquier forma! – Slaggg

22

Esta característica se introdujo en el Async CTP, que ahora se ha incorporado a .NET 4.5. Hacerlo de la siguiente manera no bloquea el hilo, sino que devuelve una tarea que se ejecutará en el futuro.

Task<MyType> new_task = Task.Delay(TimeSpan.FromMinutes(5)) 
          .ContinueWith<MyType>(/*...*/); 

(Si se utiliza el antiguo libera asíncrono, utiliza la clase estática en lugar de TaskExTask)

+1

O simplemente espere Task.Delay (TimeSpan.FromMinutes (5)); http://msdn.microsoft.com/en-us/library/hh194873(v=vs.110).aspx –

+0

+1, pero ¿alguna alternativa que no duerma para .NET 4? (Estoy usando un enfoque un poco sobre-diseñado utilizando un solo hilo con cola de prioridad basada en el montón que solo comienza nuevas tareas cuando llega el momento, sobre-diseñado ya que la gestión de colas de prioridad no es gratis) –

+0

@MiloszKrajewski 'Task.Delay' no duerme! En general, dormir una 'Tarea' (hilo) vence por completo el propósito del diseño y la filosofía de' System.Threading.Tasks.Task', y no es recomendable. Dormir nunca sería la base de una API incorporada '.NET' como' Task.Delay'; más bien se basa en el programador en el kernel del sistema operativo para crear una tarea que no se ejecuta hasta que expire el retraso. Además, Chris propuso 'await', en cuyo caso' Delay' puede que ni siquiera termine usando un hilo adicional, ya que 'async' /' await' permite que los subprocesos individuales contribuyan al avance en múltiples operaciones "bloqueadas". –

11

Puede escribir su propia función RunDelayed. Esto requiere un retraso y una función para ejecutar después de que se complete la demora.

public static Task<T> RunDelayed<T>(int millisecondsDelay, Func<T> func) 
    { 
     if(func == null) 
     { 
      throw new ArgumentNullException("func"); 
     } 
     if (millisecondsDelay < 0) 
     { 
      throw new ArgumentOutOfRangeException("millisecondsDelay"); 
     } 

     var taskCompletionSource = new TaskCompletionSource<T>(); 

     var timer = new Timer(self => 
     { 
      ((Timer) self).Dispose(); 
      try 
      { 
       var result = func(); 
       taskCompletionSource.SetResult(result); 
      } 
      catch (Exception exception) 
      { 
       taskCompletionSource.SetException(exception); 
      } 
     }); 
     timer.Change(millisecondsDelay, millisecondsDelay); 

     return taskCompletionSource.Task; 
    } 

utilizar de esta manera:

public void UseRunDelayed() 
    { 
     var task = RunDelayed(500,() => "Hello"); 
     task.ContinueWith(t => Console.WriteLine(t.Result)); 
    } 
+0

Creo que su temporizador podría ser basura recolectada antes de su ejecución ya que no tiene referencias externas. – newdayrising

Cuestiones relacionadas