Prise en charge des rapports d'avancement et des résultats supplémentaires dans .NET 4.0 « Bibliothèque parallèle de tâches »
-
20-09-2019 - |
Question
Je sais que Tâche parallèle Bibliothèque est encore en version bêta et il y a probablement moins de ressources disponibles, mais de tout ce que j'ai lu, bibliothèque donne un traitement très spécial d'ordonnancement des tâches, la gestion des exceptions et annulation .
Mais je ne trouve pas de références à les rapports d'étape et envoi des résultats supplémentaires des tâches. Ces 2 choses semblent trop importantes pour ne pas tenir compte. Pouvez-vous jeter un peu de lumière sur la façon de gérer ces tâches dans la bibliothèque parallèle ou consultez quelques articles qui les explique?
La solution
Cet exemple met à jour une barre de progression:
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++; });
});
});
}
}
Mise à jour des progrès bar à partir de l'intérieur d'un Parallel.For
Autres conseils
Ceci est l'un de mes résultats de recherche en haut et toujours pas d'exemple de progrès dans Task Parallel Library
ici ...
Aujourd'hui, je viens de tomber sur TPL parce que je veux développer de nouvelles applications multithread mais sans utiliser BackgroundWorker
(parce que je l'ai lu quelque part la tâche avec le code bien avant)
Je compiler l'exemple, réponse @Stephen Cleary, son lien assez compliqué pour de chercher des progrès, et quelques autres sites.
Ceci est l'exemple très simple comment faire Progrès et Terminé avec toute sécurité de thread d'interface utilisateur:
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);
Le code affiche 1 à 1000 dans les 10 secondes, puis ajoutez un « Terminer! » chaîne dans les fenêtres forme barre de titre. Vous pouvez voir que le TaskScheduler est la façon délicate pour créer thread d'interface utilisateur mise à jour en sécurité parce que je pense que la tâche planifiée pour être exécutée sur thread principal.
Il n'y a pas de support intégré pour cela comme ce BackgroundWorker avait.
Vous pouvez utiliser SynchronizationContext directement; il y a une excellente vidéo ici: http://www.rocksolidknowledge.com/ScreenCasts.mvc/Watch?video = TasksAndThreadAffinity.wmv
L'auteur développe deux solutions dans cette vidéo: une en utilisant SynchronizationContext et un autre à l'aide des tâches continuations. Pour votre problème, continuations ne fonctionnera pas, mais l'approche SynchronizationContext fonctionnerait très bien.
P.S. Si vous créez un code réutilisable, puis quand vous capturez SynchronizationContext.Current, vous devez tester pour nulle et (si elle est nulle), utilisez un SynchronizationContext par défaut construit à la place.
UPDATE : Je suis le code posté pour cette sur mon blog . Ma solution est en fait basée sur une Task
qui est prévue au thread de l'interface utilisateur par un TaskScheduler
qui utilise SynchronizationContext
dessous. Contrairement à la réponse acceptée, cette solution fonctionne pour les deux formes WPF et Windows.
Le TPL est pas particulièrement orientée vers le soutien de l'interface utilisateur, vous pouvez (encore) utiliser un BackgroundWorker pour cela. En ce qui concerne l'envoi ou de la transformation des résultats intermédiaires, de nouveaux collectionclasses (ConcurrentQueue) à l'appui.
Pour signaler les progrès d'une tâche async, passer un Rapport avec les données de progression. L'appelant peut décider comment gérer ce rapport d'étape (à savoir l'ignorer, ou mettre à jour l'interface utilisateur).