Équivalent de la promesse en C#
à Scala il y a une classe Promise qui pourrait être utilisée pour compléter un futur manuellement. Je suis à la recherche d'une alternative en C#.
j'écris un test et je veux qu'il ressemble à ceci:
// var MyResult has a field `Header`
var promise = new Promise<MyResult>;
handlerMyEventsWithHandler( msg =>
promise.Complete(msg);
);
// Wait for 2 seconds
var myResult = promise.Future.Await(2000);
Assert.Equals("my header", myResult.Header);
je comprends que ce n'est probablement pas le bon modèle pour C#, mais je ne pouvais pas trouver un moyen raisonnable d'atteindre la même chose, même avec un modèle quelque peu différent.
modifier: s'il vous plaît noter, que async
/ await
n'aide pas ici, car je n'ai pas de tâche à attendre! Je viens d'avoir un accès à un gestionnaire, qui sera exécuté sur un autre thread.
4 réponses
En C#:
-
Task<T>
est un futur (ouTask
pour un futur de retour d'unité). -
TaskCompletionSource<T>
est une promesse.
ainsi votre code se traduirait comme tel:
// var promise = new Promise<MyResult>;
var promise = new TaskCompletionSource<MyResult>();
// handlerMyEventsWithHandler(msg => promise.Complete(msg););
handlerMyEventsWithHandler(msg => promise.TrySetResult(msg));
// var myResult = promise.Future.Await(2000);
var completed = await Task.WhenAny(promise.Task, Task.Delay(2000));
if (completed == promise.Task)
; // Do something on timeout
var myResult = await completed;
Assert.Equals("my header", myResult.Header);
l'attente asynchrone chronométrée est un peu embarrassante, mais elle est aussi relativement rare en code réel. Pour les tests unitaires, Je ne ferais qu'une attente asynchrone régulière:
var promise = new TaskCompletionSource<MyResult>();
handlerMyEventsWithHandler(msg => promise.TrySetResult(msg));
var myResult = await promise.Task;
Assert.Equals("my header", myResult.Header);
Le brut C# équivalent sans les bibliothèques de tiers serait:
// var MyResult has a field `Header`
var promise = new TaskCompletionSource<MyResult>();
handlerMyEventsWithHandler(msg =>
promise.SetResult(msg)
);
// Wait for 2 seconds
if (promise.Task.Wait(2000))
{
var myResult = promise.Task.Result;
Debug.Assert("my header" == myResult.Header);
}
Notez qu'il est généralement préférable d'utiliser le await
/ async
à un niveau aussi élevé que possible. L'accès au Result
d'un Task
ou l'utilisation de Wait
peut dans certains cas introduire des blocages .
vous pouvez utiliser la bibliothèque C# Promises
open sourcing on Github: https://github.com/Real-Serious-Games/C-Sharp-Promise
disponible sur NuGet: https://www.nuget.org/packages/RSG.Promise /
Essayez de regarder dans le modèle asynchrone. Les tâches sont l'équivalent le plus proche dans c#.
voici un lien vers un article de MS expliquant leur utilisation.