Comment puis-je obtenir l'équivalent de la Tâche<T>.net 3.5?
J'ai un code qui est à l'aide de Task<T>
qui reporte retournant un résultat à partir d'une série d'opérations de lecture pour un court laps de temps, comme ceci:
void ReturnResponseAfterAShortDelay()
{
if (delayedResponseCancellationTokenSource != null)
delayedResponseCancellationTokenSource.Cancel(); //Cancel any pending operations and start a new one.
delayedResponseCancellationTokenSource = new CancellationTokenSource();
log.InfoFormat("Deferring response for {0} ms", Settings.Default.TimeoutMs);
Task.Delay(Properties.Settings.Default.TimeoutMs, delayedResponseCancellationTokenSource.Token)
.ContinueWith((continuation) => ReturnWhateverHasArrived(), TaskContinuationOptions.NotOnCanceled)
.Start();
}
L'idée de ce code est de retourner le résultat quand pas de nouveaux personnages sont arrivés pour un intervalle de temps spécifié.
Toutefois, en raison de facteurs hors de mon contrôle, je dois utiliser .NET 3.5, qui m'empêche à l'aide de Task<T>
, j'ai donc de revoir ce code en quelque sorte.
Comment puis-je obtenir le même résultat, sans l'aide de Task<T>
?
Clarification
Bien que le code que j'ai montré arrive à être un temps de retard, mon utilisation n'est pas limitée à retarder les choses. Il peut y avoir d'autres cas où je veux commencer un peu de 'long' interrogation tâche immédiatement. Une situation typique serait un I/O bound opération, par exemple quelque chose de l'périodiquement des requêtes à un périphérique connecté au port série, puis déclenche un événement lorsque certaines conditions sont réunies.
OriginalL'auteur Tim Long | 2014-03-19
Vous devez vous connecter pour publier un commentaire.
Un notable et pratique hack pour le codage de tels scénarios avec C# 2.0 - 4.0 est d'utiliser auto-piloté
IEnumerable
etyield
. Il permet de mettre en œuvre un asynchrone machine d'état, semblable àasync/await
de C# 5.0. De cette façon, vous gardez la pratique linéaire flux de code pour votre logique asynchrone. Tout langage C# code de contrôle des déclarations de travaux (d'ailleurs vous ne pouvez pas faireyield return
de l'intérieurtry/catch
).Par exemple, une application de console avec un minuteur:
Tout événement pourrait être emballé avec un gestionnaire qui appellent
nextStep
, semblables à celles de la minuterie de rappel. Le code devrait continuer après le correspondantyield return
, lors de l'événement.Il y a quelques implémentations de prendre avantage de cette approche, par exemple, Jeffrey Richter
AsyncEnumerator
.mre.WaitOne()
, bloque le thread en cours, si, selon la MSDN,est utilisé ici au niveau supérieur de la chaîne d'appel (
Main
). C'est une application console et que vous avez à bloc là, sinon le programme ne fera que fin. Sinon, le point clé ici estWorkAsync
et c'est non-bloquant.Je vois. Pas sûr que je vois toute utilisation du multithreading dans une application en ligne de commande. J'ai été un peu en espérant que d'appliquer quelque chose de semblable à une des formes de l'app.
OriginalL'auteur noseratio
Vous pouvez utiliser l'un des forfaits suivants, disponibles via NuGet:
Vous pouvez utiliser le TaskParallelLibrary paquet sur NuGet. Ce paquet a un nom fort et est un .NET 3.5 arrière-port de la .NET Task Parallel Library .NET 4, qui est inclus dans le Réactif Extensions.
Vous pouvez utiliser le Système.Le filetage.Les tâches.Officieux paquet sur NuGet. Cette variante de mise en œuvre utilise le Mono base de code au lieu de la mise en œuvre de Microsoft. Notez que l'assemblée inclus dans ce package n'a pas un nom fort, donc si votre bibliothèque utilise des noms alors ce n'est pas une option.
Si vous utilisez une version compilateur C# (Visual Studio 2012 ou plus récent), vous pouvez même référence TunnelVisionLabs.Enfilage et obtenir async/await une prise en charge .NET 3.5.
Bon à savoir! Mais l'Unité est livré avec son propre compilateur, et j'ai peur de son pas capable de cela, mais lui donner un essai! Thx! 🙂
OriginalL'auteur Sam Harwell
Utiliser un
Timer
(qui est en fait commentDelay
est mis en œuvre en interne).À votre travail d'édition, si vous utilisez une application asynchrone construit sur asynchrones IO, alors que asynchrone IO déjà exposer une méthode d'asynchronie. Il pourrait être un cas de base du modèle, elle pourrait accepter un rappel, il pourrait être à l'aide de
IAsyncResult
, etc.Task
est encore une autre approche possible pour la programmation asynchrone, et vous êtes certainement capable de traduire n'importe quel approche à toute autre approche, si l'une est préférable pour vous, mais en général, les gens ont tendance à coller avec n'importe quelle méthode de la sous-jacentes IO qu'ils effectuent les utilisations, sauf s'ils ont une raison impérieuse de le faire autrement.En quoi n'est-il pas de travail?
GC permettra de recueillir votre nouvel objet timer puisque vous ne gardez pas une référence. Aussi, vous ne proposons pas d'annuler la fonctionnalité.
techniquement, oui, vous avez besoin de tenir sur la Minuterie. Pour une annulation, vous pouvez simplement vérifier si l'annulation est demandée à partir de la
action
qui appelle cette méthode.ou vous pouvez simplement utiliser ThreadPool comme je l'ai illustré dans la mise à jour sur ma réponse et de ne pas compliquer votre action avec votre code d'annulation puisque c'est un peu de mauvaise conception ...
OriginalL'auteur Servy
@Servy de réponse, un peu modifié qui a fonctionné pour moi:
Code:
OriginalL'auteur T.Todua
Utilisation de pool de threads pour exécuter la méthode:
http://msdn.microsoft.com/en-us/library/kbf0f1ct(v=vs. 110).aspx
Modifier pour Servy:
La valeur par défaut du planificateur de Tâches en Parallèle de la Bibliothèque et PLINQ utilise le .NET Framework pool de threads pour la file d'attente et l'exécution de travaux. Dans l' .NET Framework 4, le pool de threads utilise les informations fournies par le Système.Le filetage.Les tâches.Type de tâche de soutenir efficacement le parallélisme à grain extrêmement fin (à court terme des unités de travail) que les tâches parallèles et des requêtes représentent souvent.
Edit 2(à cause de la rétroaction négative):
Ce code fait exactement ce que l'OP veut:
mise à jour de réponse ...
Oui, je suis consciente de ce que, cependant, cela suppose que ce que l'OP veut faire est de simplement exécuter du code dans un thread du pool. C'est pas ce que son code est fait, et ce n'est pas la solution la plus appropriée à utiliser pour lui de résoudre son problème. On dirait que vous avez regardé le titre, mais n'a pas fait de regarder le code en question.
À partir de la question de corps, vous pouvez voir que l'opération aurait utilisez tâche si elle est disponible. De la tâche par défaut est juste une couche sur ThreadPool c'est exactement ce qu'il veut - le groupe de<T> les fonctionnalités de 4,0 3,5
Le code de l'OP utilise
Task.Delay
qui, probablement, évite d'utiliser le pool de threads, puisque c'est juste en attente pour un délai d'attente et de ne pas faire tout autre travail.OriginalL'auteur Bogdan