Как я могу вызвать асинхронный метод в Main?
public class test
{
public async Task Go()
{
await PrintAnswerToLife();
Console.WriteLine("done");
}
public async Task PrintAnswerToLife()
{
int answer = await GetAnswerToLife();
Console.WriteLine(answer);
}
public async Task<int> GetAnswerToLife()
{
await Task.Delay(5000);
int answer = 21 * 2;
return answer;
}
}
Если я хочу вызвать метод Go в main(), как я могу это сделать?
Я пытаюсь использовать новые функции С#, я знаю, что могу подключить метод async к событию, и, инициировав это событие, можно вызвать метод async.
Но что, если я хочу назвать это напрямую в основном методе? Как я могу это сделать?
Я сделал что-то вроде
class Program
{
static void Main(string[] args)
{
test t = new test();
t.Go().GetAwaiter().OnCompleted(() =>
{
Console.WriteLine("finished");
});
Console.ReadKey();
}
}
Но кажется, что это мертвый замок, и на экране ничего не печатается.
Ответы
Ответ 1
Ваш метод Main
может быть упрощен. Для С# 7.1 и новее:
static async Task Main(string[] args)
{
test t = new test();
await t.Go();
Console.WriteLine("finished");
Console.ReadKey();
}
Для более ранних версий С#:
static void Main(string[] args)
{
test t = new test();
t.Go().Wait();
Console.WriteLine("finished");
Console.ReadKey();
}
Это часть красоты ключевого слова async
(и связанной с ним функциональности): использование и запутанная природа обратных вызовов значительно сокращены или устранены.
Ответ 2
Вместо Wait вам лучше использовать
new test().Go().GetAwaiter().GetResult()
так как это исключает исключения, которые обертываются в AggregateExceptions, поэтому вы можете просто окружить свой метод Go() блоком try catch (Exception ex), как обычно.
Ответ 3
После выпуска С# v7.1 методы async
main
стали доступны для использования, что устраняет необходимость в обходных путях в уже опубликованных ответах. Добавлены следующие подписи:
public static Task Main();
public static Task<int> Main();
public static Task Main(string[] args);
public static Task<int> Main(string[] args);
Это позволяет вам написать свой код следующим образом:
static async Task Main(string[] args)
{
await DoSomethingAsync();
}
static async Task DoSomethingAsync()
{
//...
}
Ответ 4
class Program
{
static void Main(string[] args)
{
test t = new test();
Task.Run(async () => await t.Go());
}
}
Ответ 5
Пока вы получаете доступ к объекту результата из возвращаемой задачи, нет необходимости вообще использовать GetAwaiter (только в том случае, если вы получаете доступ к результату).
static async Task<String> sayHelloAsync(){
await Task.Delay(1000);
return "hello world";
}
static void main(string[] args){
var data = sayHelloAsync();
//implicitly waits for the result and makes synchronous call.
//no need for Console.ReadKey()
Console.Write(data.Result);
//synchronous call .. same as previous one
Console.Write(sayHelloAsync().GetAwaiter().GetResult());
}
если вы хотите дождаться выполнения задачи и выполнить дальнейшую обработку:
sayHelloAsyn().GetAwaiter().OnCompleted(() => {
Console.Write("done" );
});
Console.ReadLine();
Если вы заинтересованы в получении результатов от sayHelloAsync и выполните дальнейшую обработку:
sayHelloAsync().ContinueWith(prev => {
//prev.Result should have "hello world"
Console.Write("done do further processing here .. here is the result from sayHelloAsync" + prev.Result);
});
Console.ReadLine();
Последний простой способ ожидания функции:
static void main(string[] args){
sayHelloAsync().Wait();
Console.Read();
}
static async Task sayHelloAsync(){
await Task.Delay(1000);
Console.Write( "hello world");
}
Ответ 6
public static void Main(string[] args)
{
var t = new test();
Task.Run(async () => { await t.Go();}).Wait();
}
Ответ 7
Используйте .Wait()
static void Main(string[] args){
SomeTaskManager someTaskManager = new SomeTaskManager();
Task<List<String>> task = Task.Run(() => marginaleNotesGenerationTask.Execute());
task.Wait();
List<String> r = task.Result;
}
public class SomeTaskManager
{
public async Task<List<String>> Execute() {
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:4000/");
client.DefaultRequestHeaders.Accept.Clear();
HttpContent httpContent = new StringContent(jsonEnvellope, Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage httpResponse = await client.PostAsync("", httpContent);
if (httpResponse.Content != null)
{
string responseContent = await httpResponse.Content.ReadAsStringAsync();
dynamic answer = JsonConvert.DeserializeObject(responseContent);
summaries = answer[0].ToObject<List<String>>();
}
}
}