2009-10-08 6 views
15

Sé que Task Parallel Library todavía está en versión beta y es probable que haya menos recursos disponibles, pero de lo que he leído, la biblioteca da un trato muy especial al task scheduling , exception handling y cancellation.Soporte de informes de progreso y resultados incrementales en .NET 4.0 "Task Parallel Library"

Pero no encuentro ninguna referencia a los informes de progreso y el envío de los resultados incrementales de tareas. Estas 2 cosas parecen demasiado importantes como para ignorarlas. ¿Puede arrojar algo de luz sobre cómo manejar estos en la Biblioteca de Tareas paralelas o consultar algunos artículos que los explican?

+0

¿alguna solución final con código fuente completo? – Kiquenet

Respuesta

9

este ejemplo se actualiza una barra de progreso:

using System; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Windows.Forms; 

class SimpleProgressBar : Form 
{ 
    [STAThread] 
    static void Main(string[] args) 
    { 
     Application.EnableVisualStyles(); 
     Application.Run(new SimpleProgressBar()); 
    } 

    protected override void OnLoad(EventArgs e) 
    { 
     base.OnLoad(e); 

     int iterations = 100; 

     ProgressBar pb = new ProgressBar(); 
     pb.Maximum = iterations; 
     pb.Dock = DockStyle.Fill; 
     Controls.Add(pb); 

     Task.ContinueWith(delegate 
     { 
      Parallel.For(0, iterations, i => 
      { 
       Thread.SpinWait(50000000); // do work here 
       BeginInvoke((Action)delegate { pb.Value++; }); 
      }); 
     }); 
    } 
} 

Updating a progress bar from inside a Parallel.For

+0

¿De dónde sacas '.Create' en Tarea? Tengo los mismos namspaces importados y no puedo encontrarlo. –

+0

@Nick: parece que MSFT puede haber cambiado ligeramente la clase de Tarea entre la Tarea paralela CTP y la versión .NET 4.0. Sugiero probar 'ContinueWith' en lugar de' Create'. –

+0

La tarea no tiene Create y ContinueWith – Praneeth

2

El TPL no se orienta sobre todo hacia el soporte de interfaz de usuario, puede (aún) utilizar un BackgroundWorker para eso. En cuanto al envío o procesamiento de resultados intermedios, existen nuevas clases de recopilación (ConcurrentQueue) para respaldar eso.

7

No hay soporte integrado para esto como lo que tenía BackgroundWorker.

Puede usar SynchronizationContext directamente; hay un video excelente aquí: http://www.rocksolidknowledge.com/ScreenCasts.mvc/Watch?video=TasksAndThreadAffinity.wmv

El autor desarrolla dos soluciones en este video: una que usa SynchronizationContext y otra que usa Continuaciones de tareas. Para su problema, las continuaciones no funcionarán, pero el enfoque SynchronizationContext funcionaría bien.

P.S. Si está creando código reutilizable, cuando capture SynchronizationContext.Current, debe probar null y (si es nulo) usar un SynchronizationContext predeterminado.

ACTUALIZACIÓN: He publicado el código para este on my blog. Mi solución se basa realmente en un Task que está programado para volver a la secuencia de la interfaz de usuario mediante un TaskScheduler que usa SynchronizationContext debajo. A diferencia de la respuesta aceptada, esta solución funcionará tanto para WPF como para Windows Forms.

+0

Acabo de crear una nueva respuesta para mostrar un ejemplo simple basado en tu blog allí. – CallMeLaNN

8

Ésta es una de mis principales resultados de la búsqueda y todavía ningún ejemplo para el progreso en Task Parallel Library aquí ...

Hoy me encontré con TPL porque quiero desarrollar una nueva aplicación multiproceso pero sin utilizar BackgroundWorker (porque leer en algún lugar sobre la tarea con buen código antes)

compilo el ejemplo de respuesta @Stephen Cleary, su enlace bastante complicado para buscar progreso, y algunos otros sitios web.

Este es el ejemplo muy simple de cómo hacer Progreso y Completado con forma segura hilo de interfaz de usuario:

 TaskScheduler currentTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 
     Task<string>.Factory.StartNew(() => 
     { 
      // loop for about 10s with 10ms step 
      for (int i = 0; i < 1000; i++) 
      { 
       Thread.Sleep(10); 
       Task.Factory.StartNew(() => 
       { 
        // this is a task created each time you want to update to the UI thread. 
        this.Text = i.ToString(); 
       }, CancellationToken.None, TaskCreationOptions.None, currentTaskScheduler); 
      } 
      return "Finished!"; 
     }) 
     .ContinueWith(t => 
     { 
      // this is a new task will be run after the main task complete! 
      this.Text += " " + t.Result; 
     }, currentTaskScheduler); 

El código se mostrará 1 a 1000 dentro de 10 segundos y luego añadir una "meta! " cadena en la barra de título de forma de ventanas. Puede ver que el TaskScheduler es la manera complicada de crear una actualización segura de subprocesos de UI porque creo que la tarea programada se ejecutará en el hilo principal.

+0

La tarea de progreso es en realidad un elemento secundario de la tarea principal que se ejecuta de forma síncrona con el hilo de la interfaz de usuario. Tengo de aquí http://www.dcomproductions.com/blog/2011/08/writing-thread-safe-event-handlers-with-the-task-parallel-library-in-net-4-0/ – CallMeLaNN

0

Para informar el progreso de una tarea asíncrona, pase un IProgress en el método asíncrono. Dentro del método, llame al Report con los datos de progreso. La persona que llama puede decidir cómo manejar ese informe de progreso (es decir, Ignorarlo o actualizar la IU).

+2

The la pregunta solicita informes de progreso dentro de .NET 4.0. IProgress no se introdujo hasta .NET 4.5. – BTownTKD

+0

Pre .NET 4.5 obviamente puede definir 'interfaz pública IProgress ' – Graham