Supporto del progresso reporting e incrementali risultati in .NET 4.0 “Task Parallel Library”

StackOverflow https://stackoverflow.com/questions/1535749

Domanda

So che Task Parallel Biblioteca è ancora in beta e ci sono probabilità di essere meno risorse a disposizione, ma da ciò che ho letto, la biblioteca offre un trattamento molto speciale per pianificazione delle attività , la gestione delle eccezioni e cancellazione .

Ma non trovo alcun riferimento a progresso del rapporto e l'invio di risultati incrementali da compiti. Questi 2 cose sembrano troppo importante per essere ignorato. Si può gettare un po 'di luce su come gestire questi in biblioteca Task Parallel o consultare alcuni articoli che li spiega?

È stato utile?

Soluzione

Questo esempio aggiorna 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++; });   
            });   
        });   
    }   
}  

Aggiornamento di un progresso bar dall'interno di una Parallel.For

Altri suggerimenti

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é ho letto da qualche parte su attività con un bel codice prima)

compilo l'esempio da @Stephen Cleary risposta, il suo legame abbastanza complicato per cercare il progresso, e di alcuni altri siti web.

Questo è il molto semplice esempio a come fare Progress e Completato con il 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 "Fine!" stringa nelle finestre formano barra del titolo. Si può vedere che la TaskScheduler è il modo più difficile per creare thread UI aggiornamento sicuro perché penso che l'operazione pianificata da eseguire sul thread principale.

Non v'è alcun supporto integrato per questo come quello che aveva BackgroundWorker.

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

L'autore sviluppa due soluzioni a questo video: uno tramite SynchronizationContext e un altro utilizzando Task continuazioni. Per il vostro problema, continuazioni non funzioneranno, ma l'approccio SynchronizationContext avrebbe funzionato bene.

P.S. Se si sta creando codice riutilizzabile, poi, quando si cattura SynchronizationContext.Current, si dovrebbe verificare per nulla e (se è null) utilizzare uno SynchronizationContext default-costruito al posto.

Aggiorna : Ho postato codice per questo sul mio blog . Mia soluzione è attualmente basato su un Task che è prevista indietro al thread UI da un TaskScheduler che utilizza SynchronizationContext sotto. A differenza della risposta accettata, questa soluzione funziona per entrambe le forme di WPF e Windows.

Il TPL non è particolarmente orientato verso il supporto dell'interfaccia utente, è possibile (ancora) utilizzare un BackgroundWorker per questo. Per quanto riguarda l'invio o la trasformazione dei risultati intermedi, ci sono nuovi collectionclasses (ConcurrentQueue) per sostenere questo.

Per segnalare i progressi da un compito asincrona, passare un IProgress nel metodo asincrono. All'interno del metodo, chiamata Rapporto con i dati di avanzamento. Il chiamante può decidere come gestire quella relazione di avanzamento (cioè ignorarlo, o aggiornare l'interfaccia utente).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top