2009-10-08 11 views
15

So che Task Parallel Library è ancora in beta e ci sono probabilmente meno risorse disponibili ma da qualsiasi cosa abbia letto, la libreria offre un trattamento molto speciale a task scheduling , exception handling e cancellation.Supporto della reportistica progressiva e dei risultati incrementali in .NET 4.0 "Task Parallel Library"

Ma non trovo alcun riferimento a progresso segnalazione e l'invio dei risultati incrementali da compiti. Queste 2 cose sembrano troppo importanti da ignorare. Puoi far luce su come gestirli in Task Parallel Library o fare riferimento ad alcuni articoli che li spiegano?

+0

qualsiasi soluzione finale con codice sorgente completo? – Kiquenet

risposta

9

questo esempio viene aggiornato una barra di avanzamento:

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

Dove stai ottenendo '.Create' in Attività? Ho importato gli stessi namspace e non riesco a trovarlo. –

+0

@Nick: Sembra che MSFT abbia potuto modificare leggermente la classe Task tra il CTP parallelo all'attività e la versione .NET 4.0. Suggerisco di provare "ContinueWith" invece di "Create". –

+0

L'attività non ha sia Create che ContinueWith – Praneeth

2

Il TPL non è particolarmente orientata verso il supporto dell'interfaccia utente, è possibile (ancora) utilizzare un BackgroundWorker per questo. Per quanto riguarda l'invio o l'elaborazione di risultati intermedi, ci sono nuove classi di raccolta (ConcurrentQueue) per supportarlo.

7

Non esiste un supporto integrato per questo come quello che ha avuto BackgroundWorker.

È possibile utilizzare direttamente SynchronizationContext; c'è un video eccellente qui: http://www.rocksolidknowledge.com/ScreenCasts.mvc/Watch?video=TasksAndThreadAffinity.wmv

L'autore sviluppa due soluzioni in questo video: una con SynchronizationContext e un'altra con Continuazioni di attività. Per il tuo problema, le continuazioni non funzioneranno, ma l'approccio SynchronizationContext funzionerebbe correttamente.

P.S. Se stai creando codice riutilizzabile, quando acquisisci SynchronizationContext.Current, dovresti testare null e (se è null) utilizzare invece un SynchronizationContext predefinito.

UPDATE: Ho pubblicato il codice per questo on my blog. La mia soluzione è in realtà basata su un Task che è pianificato per il thread UI da un TaskScheduler che utilizza SynchronizationContext in basso. A differenza della risposta accettata, questa soluzione funzionerà sia per WPF che per Windows Form.

+0

Ho appena creato una nuova risposta per mostrare un semplice esempio basato sul tuo blog lì. – CallMeLaNN

8

Questo è uno dei miei primi risultati di ricerca e ancora nessun esempio per il progresso in Task Parallel Library proprio qui ...

Oggi mi sono imbattuto in TPL perché voglio sviluppare nuove applicazioni multithread ma senza usare BackgroundWorker (perché io leggere da qualche parte sull'attività con un buon codice prima)

Compilare l'esempio da @Stephen Risposta Cleary, il suo collegamento abbastanza complicato per cercare progresso e alcuni altri siti web.

Questo è l'esempio molto semplice di come fare Progress e Completato con thread UI modo sicuro:

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

Il codice verrà visualizzato 1 a 1000 entro 10s e poi aggiungere un "Finish! " stringa nella barra del titolo di Windows. È possibile notare che TaskScheduler è il modo complicato per creare un aggiornamento sicuro dei thread dell'interfaccia utente poiché ritengo che l'attività pianificata venga eseguita sul thread principale.

+0

L'attività di avanzamento è in realtà un figlio dell'attività principale che viene eseguita in modo sincrono con il thread dell'interfaccia utente. Ho ottenuto da qui http://www.dcomproductions.com/blog/2011/08/writing-thread-safe-event-handlers-with-the-task-parallel-library-in-net-4-0/ – CallMeLaNN

0

Per segnalare l'avanzamento da un'attività asincrona, passare un IProgress nel metodo asincrono. All'interno del metodo, chiamare Report con i dati di avanzamento. Il chiamante può decidere come gestire tale rapporto sullo stato di avanzamento (ad esempio ignorarlo o aggiornare l'interfaccia utente).

+2

Il la domanda richiede la segnalazione dei progressi all'interno di .NET 4.0. IProgress non è stato introdotto fino a .NET 4.5. – BTownTKD

+0

Pre. NET 4.5 è ovviamente possibile definire 'interfaccia pubblica IProgress ' – Graham

Problemi correlati