AFAIK, tout ce qu'il sait, c'est qu'à un moment donné, sa SetResult
ou SetException
méthode est appelée pour compléter l' Task<T>
exposition à travers sa Task
propriété.
En d'autres termes, il agit en tant que producteur pour a Task<TResult>
et son achèvement.
J'ai vu ici l'exemple:
Si j'ai besoin d'un moyen d'exécuter un Func de manière asynchrone et d'avoir une tâche pour 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;
}
Ce qui pourrait être utilisé * si je n'ai pas Task.Factory.StartNew
- mais je n'avoir .Task.Factory.StartNew
Question:
Quelqu'un peut -il expliquer par exemple s'il vous plaît un scénario lié directement à TaskCompletionSource
et non à une hypothétique situation dans laquelle je n'ai pas Task.Factory.StartNew
?
c#
.net
.net-4.0
task-parallel-library
taskcompletionsource
Royi Namir
la source
la source
Réponses:
Je l'utilise principalement lorsque seule une API basée sur les événements est disponible ( par exemple les sockets Windows Phone 8 ):
Il est donc particulièrement utile lorsqu'il est utilisé avec le
async
mot clé C # 5 .la source
SomeApiWrapper
quelque part était attendu, jusqu'à ce que l'éditeur déclenche l'événement qui a provoqué la fin de cette tâche?Microsoft.Bcl.Async
package sur NuGet qui autorise lesasync/await
mots clés dans les projets .NET 4.0 (VS2012 et supérieur est recommandé).Dans mes expériences,
TaskCompletionSource
est idéal pour emballer les anciens modèles asynchrones auasync/await
modèle moderne .L'exemple le plus bénéfique auquel je peux penser est lorsque je travaille avec
Socket
. Il a l'ancienne APM et les modèles EAP, mais pas lesawaitable Task
méthodesTcpListener
etTcpClient
ont.J'ai personnellement plusieurs problèmes avec la
NetworkStream
classe et je préfère le brutSocket
. Étant donné que j'aime aussi leasync/await
motif, j'ai créé une classe d'extensionSocketExtender
qui crée plusieurs méthodes d'extension pourSocket
.Toutes ces méthodes utilisent
TaskCompletionSource<T>
pour encapsuler les appels asynchrones comme suit:Je passe le
socket
dans lesBeginAccept
méthodes afin que j'obtienne une légère augmentation des performances du compilateur sans avoir à hisser le paramètre local.Ensuite, la beauté de tout cela:
la source
Begin.. End...
instructions.Pour moi, un scénario classique d'utilisation
TaskCompletionSource
est quand il est possible que ma méthode ne doive pas nécessairement faire une opération longue. Ce qu'il nous permet de faire, c'est de choisir les cas spécifiques où nous aimerions utiliser un nouveau fil.Un bon exemple pour cela est lorsque vous utilisez un cache. Vous pouvez avoir une
GetResourceAsync
méthode qui recherche dans le cache la ressource demandée et renvoie immédiatement (sans utiliser de nouveau thread, en utilisantTaskCompletionSource
) si la ressource a été trouvée. Seulement si la ressource n'a pas été trouvée, nous aimerions utiliser un nouveau thread et le récupérer en utilisantTask.Run()
.Un exemple de code peut être vu ici: Comment exécuter de manière conditionnelle un code de manière asynchrone à l'aide de tâches
la source
Task.FromResult
pour ce faire. Bien sûr, si vous utilisez 4.0 et que vous n'avez pas deTask.FromResult
raison d'utiliser un TCS, c'est d' écrire le vôtreFromResult
.Task.FromResult
n'est disponible que depuis .NET 4.5. Avant cela, c'était le moyen d'atteindre ce comportement.Task.Run
, indiquant que c'est 4.5+. Et mon commentaire précédent portait spécifiquement sur .NET 4.0.Dans cet article de blog , Levi Botelho décrit comment utiliser le
TaskCompletionSource
pour écrire un wrapper asynchrone pour un processus de telle sorte que vous puissiez le lancer et attendre sa fin.et son utilisation
la source
Il semble que personne n'ait mentionné, mais je suppose que les tests unitaires peuvent également être considérés comme assez réels .
Je trouve
TaskCompletionSource
utile lorsque l'on se moque d'une dépendance avec une méthode asynchrone.Dans le programme en cours de test:
Dans les tests unitaires:
Après tout, cette utilisation de TaskCompletionSource semble être un autre cas «d'un objet Task qui n'exécute pas de code».
la source
TaskCompletionSource est utilisé pour créer des objets Task qui n'exécutent pas de code. Dans les scénarios du monde réel, TaskCompletionSource est idéal pour les opérations liées aux E / S. De cette façon, vous obtenez tous les avantages des tâches (par exemple, les valeurs de retour, les continuations, etc.) sans bloquer un thread pendant la durée de l'opération. Si votre "fonction" est une opération liée aux E / S, il n'est pas recommandé de bloquer un thread à l'aide d'une nouvelle tâche . Au lieu de cela, à l'aide de TaskCompletionSource , vous pouvez créer une tâche esclave pour simplement indiquer quand votre opération liée aux E / S se termine ou si elle ne fonctionne pas.
la source
Il y a un exemple du monde réel avec une explication décente dans cet article du blog "Programmation parallèle avec .NET" . Vous devriez vraiment le lire, mais voici quand même un résumé.
Le billet de blog montre deux implémentations pour:
La première implémentation illustrée est basée sur
Task<>
et présente deux défauts majeurs. Le deuxième post d'implémentation continue à les atténuer en utilisantTaskCompletionSource<>
.Voici cette deuxième implémentation:
la source
await Task.Delay(millisecondsDelay); action(); return;
ou (dans .Net 4.0)return Task.Delay(millisecondsDelay).ContinueWith( _ => action() );
Cela peut simplifier les choses à l'excès, mais la source TaskCompletion permet d'attendre un événement. Étant donné que tcs.SetResult n'est défini que lorsque l'événement se produit, l'appelant peut attendre la tâche.
Regardez cette vidéo pour plus d'informations:
http://channel9.msdn.com/Series/Three-Essential-Tips-for-Async/Lucian03-TipsForAsyncThreadsAndDatabinding
la source
Je scénario réel où j'ai utilisé
TaskCompletionSource
est lors de la mise en œuvre d'une file d'attente de téléchargement. Dans mon cas, si l'utilisateur démarre 100 téléchargements, je ne veux pas tous les déclencher en même temps et donc au lieu de renvoyer une tâche structurée, je renvoie une tâche attachée àTaskCompletionSource
. Une fois le téléchargement terminé, le thread qui fonctionne, la file d'attente termine la tâche.Le concept clé ici est que je fais un découplage lorsqu'un client demande qu'une tâche soit démarrée à partir du moment où elle démarre réellement. Dans ce cas, parce que je ne veux pas que le client ait à gérer la gestion des ressources.
notez que vous pouvez utiliser async / wait dans .net 4 tant que vous utilisez un compilateur C # 5 (VS 2012+) voir ici pour plus de détails.
la source
J'ai utilisé
TaskCompletionSource
pour exécuter une tâche jusqu'à ce qu'elle soit annulée. Dans ce cas, c'est un abonné ServiceBus que je souhaite normalement exécuter aussi longtemps que l'application s'exécute.la source
TaskCompletionSource
est aux tâches commeWaitHandle
au fil. Et nous pouvons donc utiliserTaskCompletionSource
pour effectuer une signalisation précise .Un exemple est ma réponse à cette question: délai ContentDialog après avoir cliqué sur OK
la source