Async в консольном приложении на С#?
У меня есть этот простой код:
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;
}
Великий. это компилируется.
Но скажу, что у меня консольное приложение, и я хочу запустить код выше (вызов SumTwoOperationsAsync()
)
static void Main(string[] args)
{
SumTwoOperationsAsync();
}
Но я читал, что (при использовании sync
) мне нужно полностью синхронизировать вверх и вниз:
Вопрос: Это значит, что моя функция Main
должна быть отмечена как async
?
Ну, он не может быть, потому что есть ошибка компиляции:
точка входа не может быть помечена модификатором 'async'
Если я понимаю асинхронный материал, поток войдет в функцию Main
---- > SumTwoOperationsAsync
---- > вызовет обе функции и не будет. но до SumTwoOperationsAsync
Что мне не хватает?
Ответы
Ответ 1
В большинстве типов проектов ваши async
"вверх" и "вниз" заканчиваются обработчиком события async void
или возвращают Task
в вашу инфраструктуру.
Однако приложения консоли не поддерживают это.
Вы можете либо просто выполнить Wait
в возвращаемой задаче:
static void Main()
{
MainAsync().Wait();
// or, if you want to avoid exceptions being wrapped into AggregateException:
// MainAsync().GetAwaiter().GetResult();
}
static async Task MainAsync()
{
...
}
или вы можете использовать свой собственный контекст, как тот, который я написал:
static void Main()
{
AsyncContext.Run(() => MainAsync());
}
static async Task MainAsync()
{
...
}
Дополнительная информация для async
Консольные приложения в моем блоге.
Ответ 2
Вот самый простой способ сделать это
static void Main(string[] args)
{
Task t = MainAsync(args);
t.Wait();
}
static async Task MainAsync(string[] args)
{
await ...
}
Ответ 3
Как быстрое и очень ограниченное решение:
Задача. Результат
Обе задачи Task.Result и Task.Wait не позволят улучшить масштабируемость при использовании с I/O, поскольку они вызовут блокировку вызывающего потока, ожидая завершения ввода-вывода.
Когда вы вызываете .Result на неполную задачу, поток, выполняющий этот метод, должен сидеть и ждать завершения задачи, что заставляет поток выполнять любую другую полезную работу. Это отрицает преимущества асинхронного характера задачи.
notasync
Ответ 4
Мое решение. JSONServer - это класс, который я написал для запуска сервера HttpListener в окне консоли.
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);
}
}