asincrónico en la aplicación de la consola en C#?
.net-4.5 async-await (4)
Esta pregunta ya tiene una respuesta aquí:
Tengo este código simple:
public static async Task<int> SumTwoOperationsAsync()
{
var firstTask = GetOperationOneAsync();
var secondTask = GetOperationTwoAsync();
return await firstTask + await secondTask;
}
private async Task<int> GetOperationOneAsync()
{
await Task.Delay(500); // Just to simulate an operation taking time
return 10;
}
private async Task<int> GetOperationTwoAsync()
{
await Task.Delay(100); // Just to simulate an operation taking time
return 5;
}
Estupendo. esto compila
Pero digamos que tengo una aplicación de consola y quiero ejecutar el código anterior (llamando a SumTwoOperationsAsync()
)
static void Main(string[] args)
{
SumTwoOperationsAsync();
}
Pero lo he leído (cuando uso la sync
) Tengo que sincronizar todo el camino hacia arriba y hacia abajo :
Pregunta : Entonces, ¿esto significa que mi función Main
debe estar marcada como async
?
Bueno, no puede ser porque hay un error de compilación:
un punto de entrada no se puede marcar con el modificador ''async''
Si entiendo las cosas de asincronización, el hilo entrará en la función Main
----> SumTwoOperationsAsync
----> llamará a ambas funciones y saldrá. pero hasta el SumTwoOperationsAsync
Qué me estoy perdiendo ?
Como una solución rápida y de gran alcance:
Tanto Task.Result como Task.Wait no permitirán mejorar la escalabilidad cuando se utilizan con E / S, ya que harán que el hilo de llamada permanezca bloqueado esperando a que termine la E / S.
Cuando llamas .Result en una Tarea incompleta, el hilo que ejecuta el método tiene que sentarse y esperar a que la tarea se complete, lo que impide que el hilo haga otro trabajo útil mientras tanto. Esto niega el beneficio de la naturaleza asincrónica de la tarea.
En la mayoría de los tipos de proyectos, su async
"arriba" y "abajo" finalizará en un controlador de eventos async void
o devolverá una Task
a su marco de trabajo.
Sin embargo, las aplicaciones de la consola no son compatibles.
Puede hacer una Wait
en la tarea devuelta:
static void Main()
{
MainAsync().Wait();
// or, if you want to avoid exceptions being wrapped into AggregateException:
// MainAsync().GetAwaiter().GetResult();
}
static async Task MainAsync()
{
...
}
o puedes usar tu propio contexto como el que escribí :
static void Main()
{
AsyncContext.Run(() => MainAsync());
}
static async Task MainAsync()
{
...
}
Más información para las aplicaciones de la consola async
está en mi blog .
Esta es la forma más simple de hacer esto
static void Main(string[] args)
{
Task t = MainAsync(args);
t.Wait();
}
static async Task MainAsync(string[] args)
{
await ...
}
Mi solución. JSONServer es una clase que escribí para ejecutar un servidor HttpListener en una ventana de consola.
class Program
{
public static JSONServer srv = null;
static void Main(string[] args)
{
Console.WriteLine("NLPS Core Server");
srv = new JSONServer(100);
srv.Start();
InputLoopProcessor();
while(srv.IsRunning)
{
Thread.Sleep(250);
}
}
private static async Task InputLoopProcessor()
{
string line = "";
Console.WriteLine("Core NLPS Server: Started on port 8080. " + DateTime.Now);
while(line != "quit")
{
Console.Write(": ");
line = Console.ReadLine().ToLower();
Console.WriteLine(line);
if(line == "?" || line == "help")
{
Console.WriteLine("Core NLPS Server Help");
Console.WriteLine(" ? or help: Show this help.");
Console.WriteLine(" quit: Stop the server.");
}
}
srv.Stop();
Console.WriteLine("Core Processor done at " + DateTime.Now);
}
}