Comment faire Tâche awaitable
Hier, j'ai commencé à jouer avec Microsoft async CTP de la bibliothèque, et nulle part je ne pouvais pas trouver la bonne mise en œuvre de la awaitable Tâche. Je sais qu'il doit y avoir la mise en œuvre de ce genre?:
public struct SampleAwaiter<T>
{
private readonly Task<T> task;
public SampleAwaiter(Task<T> task) { this.task = task; }
public bool IsCompleted { get { return task.IsCompleted; } }
public void OnCompleted(Action continuation) { TaskEx.Run(continuation); }
public T GetResult() { return task.Result; }
}
Mais comment pourrais-je maintenant de mettre en œuvre une tâche qui, disons-le, attendez 5 secondes, et le retourner une chaîne de caractères, par exemple "Hello World"?
Une façon est d'utiliser des Tâches directement comme ceci:
Task<string> task = TaskEx.Run(
() =>
{
Thread.Sleep(5000);
return "Hello World";
});
string str = await task;
Mais comment pourrais-je le faire avec le awaitable mise en œuvre? Ou ai-je mal compris tout?
Merci pour toute information/aide 🙂
async/await s'applique aux méthodes, pas de Tâches.
Dans ce cas étroite, vous pouvez le faire
attendre ne s'applique pas aux méthodes. Il s'applique à toute expression qui s'évalue à la Tâche ou à la Tâche(T). C'est une erreur commune.
await
s'applique à des expressions qui ont un adapté GetAwaiter()
mise en œuvre, qui Task
ne - so await
s'applique à Task
(dans un sens)Dans ce cas étroite, vous pouvez le faire
await TaskEx.Delay(5000);
, mais vous aurez à étudier de plus, pour votre cas général. Le await
mot clé de recherche GetAwaiter
, et plus généralement tout ce qui est apte à GetAwaiter
peut être utilisé avec les attendent. Jon Skeet a une grande série dans son blog disecting vous attendent dans le plus grand détail.attendre ne s'applique pas aux méthodes. Il s'applique à toute expression qui s'évalue à la Tâche ou à la Tâche(T). C'est une erreur commune.
OriginalL'auteur DavorinP | 2011-08-07
Vous devez vous connecter pour publier un commentaire.
La clé ici est
AsyncCtpThreadingExtensions.GetAwaiter
qui fournit ces méthodes via une méthode d'extension. Depuis l'implémentation asynchrone est modèle base (comme LINQ), plutôt que liée à une interface spécifique, il peut venir de partout (c'estTaskAwaiter
dans ce cas).Votre code écrit est awaitable. Par exemple:
Ce imprime
Hello World
au bout de 5 secondes.à partir de zéro? J'ai blogué sur ce ici, et à gauche un exemple dans le BookSleeve source, mais je bientôt conclu qu'il est préférable d'utiliser TaskCompletionSource - pré-existant et plus rapide que ma version.
Upvote pour l'utilisation du mot "burninate'
OriginalL'auteur Marc Gravell
Plus d'un an plus tard
Après l'utilisation asynchrone attendent depuis plus d'un an maintenant, je sais que certaines choses au sujet de async je l'ai écrit dans ma réponse originale à cette question ne sont pas correctes, bien que le code dans la réponse est encore correct. Hera sont deux liens que m'a aidé énormément à comprendre comment asynchrone attendent oeuvres.
Cette interview Eric Lippert montre une excellente analogie pour async-attendent. De recherche, quelque part dans le milieu pour async-vous attendent.
Dans cet article, le toujours très serviable Eric Lippert montre quelques bonnes pratiques pour async-attendent
Réponse originale à cette question
OK, voici un exemple complet qui m'a aidé pendant le processus d'apprentissage.
Supposons que vous avez une lente calculatrice, et que vous souhaitez utiliser en appuyant sur un bouton. Pendant ce temps vous voulez que votre INTERFACE utilisateur de rester sensible, et peut-être même faire d'autres choses. Lorsque la calculatrice est fini, vous voulez afficher le résultat.
Et de cours: l'utilisation async /await pour cela, et aucune de ces méthodes comme l'événement de drapeaux et d'attente pour ces événements à définir.
Ici est la lenteur de la calculatrice:
Si vous souhaitez utiliser ce mode asynchrone lors de l'utilisation asynchrone attendent que vous avez à utiliser les groupes de travail.Exécuter(...) pour démarrer de manière asynchrone. La valeur de retour de
Task.Run
est un awaitable Tâche:Task
si la valeur de retour de la fonction que vous Exécutez est nulleTask<TResult>
si la valeur de retour de la fonction que vous exécutez estTResult
Vous pouvez commencer la Tâche, faire autre chose, et quand vous avez besoin le résultat de la Tâche que vous tapez vous attendent. Il y a un inconvénient:
Si vous voulez 'attendre' votre fonction doit être asynchrone et retour
Task
au lieu devoid
ouTask<TResult>
au lieu deTResult
.Voici le code qui s'exécute de la lenteur de la calculatrice.
Il est pratique courante de mettre fin à l'identifiant d'une fonction async avec async.
La SlowAdd est démarré en tant que fonction async, et votre thread continue. Une fois qu'il a besoin de la réponse qu'il attend pour la Tâche. La valeur de retour est la TResult, qui dans ce cas est un int.
Si vous n'avez rien d'utile à faire le code devrait ressembler à ceci:
Noter que SlowAddAsync est déclarée une fonction async, donc tout le monde qui utilise cette fonction async devrait également être asynchrone et le retour de la Tâche ou des Tâches
<TResult
>:La bonne chose à propos async /await, c'est que vous n'avez pas à jouer avec ContinueWith attendre jusqu'à ce que la tâche précédente est terminée. Utilisez simplement vous attendent, et vous savez que la tâche est terminée et que vous avez la valeur de retour. De l'instruction après l'attendent est ce que vous auriez normalement faire dans la ContinueWith.
Par ailleurs, votre Tâche.Run n'a pas à appeler une fonction, vous pouvez également mettre un bloc de rapport:
Cependant, la bonne chose à propos d'une fonction distincte, c'est que vous donner à ceux qui n'ont pas besoin /envie /comprendre asynchrone, la possibilité d'utiliser la fonction sans async /await.
Rappelez-vous:
"Mais mon gestionnaire d'événement ne peut pas retourner une Tâche!"
Vous avez raison, donc c'est la seule exception:
Donc en cliquant sur le bouton, la async gestionnaire d'événement conserver l'INTERFACE utilisateur réactive:
Cependant, vous avez encore de déclarer le gestionnaire d'événements asynchrones
Il y a async fonctions pour
- L'accès à Internet
- Flux de Lecture et d'Écriture
- Base de données access
- etc.
À utiliser vous n'avez pas à appeler de la Tâche.Terme, ils sont déjà de retour Tâche
<TResult
> il suffit de les appeler, de continuer à faire vos propres trucs et quand vous avez besoin d'une réponse attendent pour la Tâche et l'utilisation de la TResult.Lancer plusieurs tâches et d'attendre pour eux de terminer
Si vous commencez à plusieurs tâches et vous voulez attendre pour tous à la fin, utilisez la Tâche.WhenAll(...) PAS la Tâche.Attendre
Tâche.Attendre renvoie un void. De la tâche.WhenAll retourne une Tâche, de sorte que vous pouvez attendre.
Une fois qu'une tâche est terminée, la valeur de retour est déjà le retour de l'attendent, mais si vous y attendent Tâche.WhenAll ( nouvelle Tâche[]{TaskA, TaskB, TaskC});
vous devez utiliser la Tâche
<TResult
>.Résultat de la propriété de connaître le résultat d'une tâche:Si l'une des tâches déclenche une exception, il est enveloppé comme InnerExceptions dans un AggregateException. Donc, si vous attendez de la Tâche.WhenAll, être prêt à attraper le AggregateException et vérifier la innerExceptions pour voir toutes les exceptions levées par les tâches que vous avez commencé. Utiliser la fonction AggregateException.Aplatissez-la pour accéder à l'exceptions de plus en plus facilement.
Intéressant de lire à propos de l'annulation:
MSDN à propos de l'Annulation dans la gestion des threads
Enfin: vous utilisez du Fil.Le sommeil(...). La version asynchrone est la Tâche.Delay(Délai):
Si vous utilisez cette fonction de votre programme de garde adapté.
OriginalL'auteur Harald Coppoolse
J'ai fini avec cet exemple de code ... est-ce la bonne mise en œuvre de la awaitable modèle?
}
Task.Factory.FromAsync
, ou de rechercher les méthodes les nomsxxxTaskAsync
.Mais est-ce la bonne mise en œuvre de la awaitable modèle?
Je pense que votre awaiter besoins pour mettre en œuvre BeginAwait et EndAwait. Vous devriez vraiment lire Jon Skeet le blog de la série sur la coutume awaiters comme il a mentionné un grand nombre de gotcha lors de l'écriture.
Oui, BeginAwait et EndAwait était dans l'ancienne version du CTP ... dans la nouvelle version de la awaiter modèle a changé.
OriginalL'auteur DavorinP