É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.

40
demandé sur eddyP23 2016-08-17 15:24:22

4 réponses

En C#:

  • Task<T> est un futur (ou Task 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);
54
répondu Stephen Cleary 2016-08-17 13:47:56

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 .

8
répondu Dark Falcon 2017-05-23 12:34:27

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 /

5
répondu Mathew Sachin 2016-08-17 12:31:53

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.

2
répondu Rich Linnell 2016-08-17 12:27:36