C# async/await Progrès de l'événement sur la Tâche<> objet
Je suis complètement novice en C# 5 nouvelle async
/await
mots-clés et je suis intéressé à la meilleure façon de mettre en œuvre un événement progress.
Maintenant je préfère le il si un Progress
événement était sur le Task<>
lui-même. Je sais que je pourrais juste mettre de l'événement dans la classe qui contient la méthode asynchrone et de passer à quelque sorte de l'état de l'objet dans le gestionnaire d'événements, mais pour moi, cela semble être plus d'une solution à une solution. J'ai peut également différentes tâches à feu hors de gestionnaires d'événements dans différents objets, ce qui semble désordonné de cette façon.
Est-il un moyen que je pouvais faire quelque chose de similaire à la suivante?:
var task = scanner.PerformScanAsync();
task.ProgressUpdate += scanner_ProgressUpdate;
return await task;
OriginalL'auteur Connell | 2013-03-14
Vous devez vous connecter pour publier un commentaire.
Tout simplement,
Task
n'est pas de soutenir les progrès. Cependant, il y a déjà une façon traditionnelle de faire cela, à l'aide de laIProgress<T>
interface. Le Basée sur les tâches du Modèle Asynchrone suggère de surcharger vos méthodes asynchrones (où il fait sens) pour permettre aux clients de passer unIProgess<T>
mise en œuvre. Votre méthode async ferait ensuite rapport des progrès réalisés par les que.Le Windows Runtime (WinRT) API ne ont indicateurs de progrès intégré, dans le
IAsyncOperationWithProgress<TResult, TProgress>
etIAsyncActionWithProgress<TProgress>
types... donc si vous êtes en train d'écrire pour WinRT, ceux qui sont utile dans la recherche - mais à lire les commentaires ci-dessous.async
méthode avecIProgress<T>
(C# suivants conventions) et ensuite utiliserAsyncInfo.Run
de l'envelopper dans unIAsyncOperationWithProgress
/IAsyncActionWithProgress
plutôt que la mise en œuvre de ces interfaces directement.Eh bien cela dépend si vous êtes en train de penser à propos de la de l'appelant ou mise. Si vous essayez d'exposer des fonctionnalités pour les autres, pour l'appeler, j'aurais pensé le WinRT "native" types serait plus approprié. Évidemment, il existe divers convertisseurs entre les deux.
Il est plus facile de suivre C# conventions en C#, et d'utiliser des emballages (
AsTask
/AsyncInfo
) les frontières. Ainsi, un composant WinRT implémenté en C# serait de retour le WinRT type d'interface, mais mettra en œuvre à l'aide régulièreasync
enveloppé dansAsyncInfo
.Juste assez, je vais prendre votre mot pour cela 🙂
OriginalL'auteur Jon Skeet
L'approche recommandée est décrite dans le Basée sur les tâches du Modèle Asynchrone de la documentation, ce qui donne à chaque méthode asynchrone son propre
IProgress<T>
:Utilisation:
Notes:
progress
paramètre peut êtrenull
si l'appelant n'a pas besoin des rapports de progrès, alors assurez-vous de vérifier cela dans votreasync
méthode.Progress
.Progress<T>
type de capturer le contexte actuel (par exemple, l'INTERFACE utilisateur contexte) de la construction et de rehausser sonProgressChanged
cas dans ce contexte. Si vous n'avez pas à vous soucier de marshaling de retour vers le thread de l'INTERFACE utilisateur avant d'appelerReport
.Presque. Ce que je veux dire c'est que lorsque la
Report
méthode est terminée (et retourné), la déclaration n'a pas encore eu lieu. Si votreT
est mutable et vous changer après le passage àReport
, alors vous avez une condition de course. La déclarante effective peut voir l'ancienne valeur, la nouvelle valeur, ou un mélange (c'est à dire, l'ancienne valeur de certains champs et la nouvelle valeur pour les autres).Oui ça fait beaucoup plus de sens maintenant, je vous remercie. J'ai lu quelques-uns de vos blogs etc où vous l'avez mentionné la condition de la course, mais il n'était pas immédiatement évident jusqu'à ce que j'ai lu cette question. Merci
Il n'y a pas de garantie alors que le ProgressChanged délégué obtient quel est le Rapport()'d dans l'ordre? De ma compréhension, il semblerait même si l'objet passé est immuable, si je mettre à jour une interface avec les derniers T j'ai reçu il y a une chance que je vais le mettre à jour pour afficher plus d'informations périmées parce que j'ai reçu d'un ancien progrès de l'objet après une nouvelle.
Techniquement, il n'existe aucune commande exigence. Cependant, chaque mise en œuvre, je suis conscient de ne maintenir l'ordre.
OriginalL'auteur Stephen Cleary
J'ai eu à reconstituer cette réponse de plusieurs messages que j'ai été à essayer de comprendre comment faire ce travail pour le code qui est moins trivial (c'est à dire des événements de notifier les modifications).
Supposons que vous avez un synchrones élément de processeur qui annoncera le numéro de l'élément, il est sur le point de commencer à travailler sur. Pour mon exemple, je vais me contenter de manipuler le contenu du Processus de bouton, mais vous pouvez facilement mettre à jour une barre de progression etc.
La partie principale de ceci est la fermeture de plus de la
Progress<>
variable à l'intérieur deItemProcessed
abonnement. Cela permet à tout àJust works ™
.OriginalL'auteur Chris Marisic