Quand doit-TaskCompletionSource<T> être utilisé?
Autant que je sache, tout ce qu'il sait, c'est qu'à un certain point, son SetResult
ou SetException
méthode est appelée à remplir le Task<T>
exposée par sa Task
propriété.
En d'autres termes, il agit en tant que producteur pour une Task<TResult>
et de son achèvement.
J'ai vu ici l'exemple :
Si j'ai besoin d'un moyen pour exécuter une touche Func de manière asynchrone et ont une Tâche
afin de représenter cette opération.
public static Task<T> RunAsync<T>(Func<T> function)
{
if (function == null) throw new ArgumentNullException(“function”);
var tcs = new TaskCompletionSource<T>();
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
T result = function();
tcs.SetResult(result);
}
catch(Exception exc) { tcs.SetException(exc); }
});
return tcs.Task;
}
Qui pourrait être utilisé *si je n'avais pas Task.Factory.StartNew
-
Mais je ne ont Task.Factory.StartNew
.
Question:
Quelqu'un peut expliquer, par exemple, un scénario de directement à TaskCompletionSource
et pas à un hypothétique situation dans laquelle je n'ai pas Task.Factory.StartNew
?
- TaskCompletionSource est principalement utilisé pour l'emballage de l'événement en fonction api asynchrone à la Tâche sans se faire de nouveaux Threads.
Vous devez vous connecter pour publier un commentaire.
J'utilise surtout quand seulement un événement à partir de l'api est disponible (par exemple, windows phone 8 sockets):
Il est donc particulièrement utile lorsqu'il est utilisé avec le c#5
async
mot-clé.SomeApiWrapper
est attendu à quelque part , jusqu'à l'éditeur déclencher l'événement qui cause cette tâche à remplir ?await
de mots clés de c# 5.Microsoft.Bcl.Async
sur NuGet package qui permet à l'async/await
mots clés .NET 4.0 projets (VS2012 et plus est recommandé).SomeApi.Done
gestionnaire d'événement?Dans mes expériences,
TaskCompletionSource
est idéal pour l'emballage de vieux modèles asynchrones à la moderneasync/await
modèle.La plus bénéfique exemple, je pense, lorsque l'on travaille avec
Socket
. Il a la vieille APM et PAE des modèles, mais pas leawaitable Task
méthodesTcpListener
etTcpClient
ont.Personnellement, j'ai plusieurs problèmes avec le
NetworkStream
classe et préférez les premièresSocket
. L'être que j'aime aussi leasync/await
modèle, j'ai fait une classe d'extensionSocketExtender
ce qui crée de nombreuses méthodes d'extension pourSocket
.L'ensemble de ces méthodes, l'utilisation de
TaskCompletionSource<T>
pour envelopper les appels asynchrones comme suit:Je passe le
socket
dans leBeginAccept
méthodes de sorte que je reçois une légère augmentation des performances hors du compilateur de ne pas avoir réussi à hisser le paramètre local.Puis la beauté de tout cela:
Begin.. End...
consolidés.Pour moi, un scénario classique pour l'utilisation de
TaskCompletionSource
est quand il est possible que ma méthode ne nécessairement avez à faire un temps long de l'opération. Ce qu'il nous permet de le faire est de choisir les cas spécifiques où nous aimerions utiliser un nouveau thread.Un bon exemple de cela est lorsque vous utilisez un cache. Vous pouvez avoir un
GetResourceAsync
méthode, qui a l'air dans le cache pour la ressource demandée et renvoie à la fois (sans l'aide d'un nouveau fil de discussion, en utilisantTaskCompletionSource
) si la ressource a été trouvé. Seulement si la ressource n'a pas été trouvé, nous aimerions utiliser un nouveau fil de discussion, et de la récupérer à l'aide deTask.Run()
.Un exemple de code peut être vu ici: Comment faire pour exécuter conditionnellement un code asynchonously à l'aide de tâches
Task.FromResult
pour ce faire. Bien sûr, si vous utilisez 4.0 et qui n'ont pasTask.FromResult
ce que vous souhaitez utiliser un TCS pour est de écrire votre propreFromResult
.Task.Run
, indiquant qu'il est de 4,5+. Et mon commentaire précédent traitée de manière spécifique .NET 4.0.Dans ce blog, Levi Botelho décrit comment utiliser le
TaskCompletionSource
à écrire un asynchrones wrapper pour un Processus tel que vous pouvez le lancer et d'attendre sa fin.et son utilisation
Il semble que pas mentionné, mais je suppose que les tests unitaires trop peut être considéré comme la vraie vie assez.
Je trouve
TaskCompletionSource
être utile lorsque les moqueries d'une dépendance avec une méthode asynchrone.Dans le cadre du programme sous test:
Dans les tests unitaires:
Après tout, cette utilisation de TaskCompletionSource semble un autre cas de "un objet Tâche qui n'exécute pas le code".
TaskCompletionSource est utilisé pour créer Tâche objets qui ne sont pas d'exécuter du code.
Dans des Scénarios du Monde Réel TaskCompletionSource est idéal pour les I/O les opérations liées. De cette façon, vous obtenez tous les avantages de tâches (par exemple, les valeurs de retour, les continuations, etc) sans bloquer un thread pour la durée de l'opération. Si votre "fonction" est un IO opération, il n'est pas recommandé de bloquer un thread à l'aide de une nouvelle Tâche. Au lieu d'utiliser TaskCompletionSource vous pouvez créer un esclave tâche il vous suffit d'indiquer lors de votre I/O bound opération se termine ou les défauts.
Il y a un monde réel exemple avec une explication décente dans ce poste à partir de la "Programmation Parallèle avec .NET" blog. Vous devriez vraiment lire, mais voici un résumé de toute façon.
Le blog montre deux implémentations pour:
La première mise en œuvre est indiqué sur
Task<>
et a deux défauts majeurs. La deuxième mise en œuvre de poste continue à les atténuer en utilisantTaskCompletionSource<>
.Voici cette deuxième mise en œuvre:
await Task.Delay(millisecondsDelay); action(); return;
ou (dans .Net 4.0)return Task.Delay(millisecondsDelay).ContinueWith( _ => action() );
Cela peut être trop simplifier les choses, mais le TaskCompletion source permet d'attendre sur un événement. Depuis le tcs.SetResult est seulement une fois que l'événement se produit, l'appelant peut attendre sur la tâche.
Regardez cette vidéo pour mieux comprendre:
http://channel9.msdn.com/Series/Three-Essential-Tips-for-Async/Lucian03-TipsForAsyncThreadsAndDatabinding
J'monde réel scénario où j'ai utilisé
TaskCompletionSource
est lors de l'implémentation d'une file d'attente de téléchargement. Dans mon cas, si l'utilisateur commence 100 téléchargements je ne veux pas le feu tous à la fois et donc, au lieu de retourner un strated de la tâche I retour une tâche attaché àTaskCompletionSource
. Une fois que le téléchargement est achevé le thread de travail de la file d'attente termine la tâche.Le concept clé ici est que je suis découplage lorsqu'un client demande une tâche doit être démarré à partir de quand il obtient réellement commencé. Dans ce cas, parce que je ne veux pas le client d'avoir à traiter avec la gestion des ressources.
notez que vous pouvez utiliser async/await dans .net 4, tant que vous êtes à l'aide de C# 5 compilateur (VS 2012+) voir ici pour plus de détails.
J'ai utilisé
TaskCompletionSource
pour exécuter une Tâche jusqu'à ce qu'elle soit annulée. Dans ce cas, c'est un ServiceBus abonné que normalement, je veux courir aussi longtemps que l'application s'exécute.