tag - Promesa equivalente en C#
summary tag in c# (5)
Cía#:
-
Task<T>
es un futuro (oTask
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);
}
Intenta buscar en el modelo asíncrono. Las tareas son el equivalente más cercano en c #.
Puede usar la biblioteca de promesas de C #
Fuente abierta en Github: https://github.com/Real-Serious-Games/C-Sharp-Promise
Disponible en NuGet: https://www.nuget.org/packages/RSG.Promise/