typeparam tag cref c# promise async-await task future

tag - Promesa equivalente en C#



summary tag in c# (5)

Cía#:

  • Task<T> es un futuro (o Task para un futuro de retorno de unidad).
  • TaskCompletionSource<T> es una promesa.

Entonces su código se traduciría como tal:

// 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);

La "espera asincrónica temporizada" es un poco incómoda, pero también es relativamente poco común en el código del mundo real. Para las pruebas unitarias, simplemente haría una espera asincrónica regular:

var promise = new TaskCompletionSource<MyResult>(); handlerMyEventsWithHandler(msg => promise.TrySetResult(msg)); var myResult = await promise.Task; Assert.Equals("my header", myResult.Header);

En Scala hay una clase Promesa que podría usarse para completar un Futuro manualmente. Estoy buscando una alternativa en C #.

Estoy escribiendo una prueba y quiero que se vea similar a esto:

// 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);

Entiendo que probablemente este no sea el patrón correcto para C #, pero no pude encontrar una manera razonable de lograr lo mismo, incluso con un patrón algo diferente.

EDITAR: tenga en cuenta que async / await no ayuda aquí, ¡ya que no tengo una tarea que esperar! Solo tengo acceso a un controlador que se ejecutará en otro hilo.


El equivalente aproximado de C # sin bibliotecas de terceros sería:

// 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); }

Tenga en cuenta que, por lo general, es mejor utilizar el modo de await / async al nivel más alto posible. Acceder al Result de una Task o usar Wait puede en algunos casos introducir puntos muertos .


Esta es la forma de hacer promesas de la vieja escuela.
En aquel entonces, creo que se llamaba sincronización :)

MyResult result = null; var are = new AutoResetEvent(false); handlerMyEventsWithHandler( msg => {result = msg; are.Set();} ); // Wait for 2 seconds if(!are.WaitOne(2000)) {/* handle timeout... */} Assert.Equals("my header", myResult.Header);

Solo por lo completo: demasiado grande para un comentario.
Estoy de acuerdo con la respuesta de Stephen Cleary .

Pero si está construyendo una fachada alrededor de algún código heredado, esto se puede usar para envolver API antiguas en una tarea como:

public Task<MyResult> GetResultAsync() { MyResult result = null; var are = new AutoResetEvent(false); handlerMyEventsWithHandler(msg => { result = msg; are.Set(); }); are.WaitOne(); return Task.FromResult(result); }