Promesa equivalente en C#
En Scala hay una clase Promise 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 esta:
// 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 este probablemente 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! Me solo tienes un acceso a un controlador que se ejecutará en otro hilo.
4 answers
En C#:
-
Task<T>
es un futuro (oTask
para un futuro de retorno de unidad). -
TaskCompletionSource<T>
es una promesa.
Así que 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 código del mundo real. Para las pruebas unitarias, solo haría una espera asíncrona regular:
var promise = new TaskCompletionSource<MyResult>();
handlerMyEventsWithHandler(msg => promise.TrySetResult(msg));
var myResult = await promise.Task;
Assert.Equals("my header", myResult.Header);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-17 13:47:56
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 await
/async
a un nivel tan alto como sea posible. Acceder a Result
de un Task
o usar Wait
puede en algunos casos introducir bloqueos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:27
Puede usar la biblioteca de promesas de C#
Código Abierto en Github: https://github.com/Real-Serious-Games/C-Sharp-Promise
Disponible en NuGet: https://www.nuget.org/packages/RSG.Promise/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-17 12:31:53
Intente buscar en el modelo asincrónico. Las tareas son el equivalente más cercano en c#.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-17 12:27:36