Supporto del progresso reporting e incrementali risultati in .NET 4.0 “Task Parallel Library”
-
20-09-2019 - |
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?
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.