Асинхронное программирование пытается понять, как работает ожидание - PullRequest
0 голосов
/ 15 сентября 2018

Итак, я изучаю некоторые основные асинхронные программы и следую этому уроку: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/ Однако вывод, который я получаю, отличается от того, что я ожидаю.

Вот мой код:

private async void btn1_Click(object sender, EventArgs e)
{
   await TestAsync();
   Console.WriteLine("terminate");
}

private async Task TestAsync()
{
   string str = await Todo();
   await Task.Delay(500);  //added await operator as per FCin advice
   Console.WriteLine(str);
}

private async Task<string> Todo()
{
   await Task.Delay(3000); //added await operator as per FCin advice
   return "return from async task";
}

Начиная с нажатия btn1, сработает метод btn1_Click. Сначала это вызовет TestAsync (). Поскольку первая строка метода TestAsync заключается в ожидании асинхронного метода, я понимаю, что в этот момент оператор await должен приостановить TestAsync и вернуть управление вызывающей стороне TestAsync, которая является btn1_Click. Это должно вывести «terminate», а затем программа должна терпеливо дождаться завершения TestAsync и в итоге вывести «« return from async task ». Однако вывод, который я получаю, в обратном порядке, и я пытаюсь понять, почему.

Итак, я исправил это так, что TestAsync теперь ожидается в методе btn1_Click. Также я изменил спящий поток на задержку задачи, но я все еще получаю тот же вывод ...

Edit2: код, который я использую в качестве примера

// 1. Three things to note in the signature:  
//  - The method has an async modifier.   
//  - The return type is Task or Task<T>. (See "Return Types" section.)  
//    Here, it is Task<int> because the return statement returns an integer.  
//  - The method name ends in "Async."  
async Task<int> AccessTheWebAsync()  
{   
// 2. You need to add a reference to System.Net.Http to declare client.  
HttpClient client = new HttpClient();  

// 3. GetStringAsync returns a Task<string>. That means that when you await 
// the task you'll get a string (urlContents).  
Task<string> getStringTask = 
client.GetStringAsync("http://msdn.microsoft.com");  

// 4 .You can do work here that doesn't rely on the string from 
//GetStringAsync.  
DoIndependentWork();  

// 5. The await operator suspends AccessTheWebAsync.  
//  - AccessTheWebAsync can't continue until getStringTask is complete.  
//  - Meanwhile, control returns to the caller of AccessTheWebAsync.  
//  - Control resumes here when getStringTask is complete.   
//  - The await operator then retrieves the string result from getStringTask.  
string urlContents = await getStringTask;  

// 6. The return statement specifies an integer result.  
// Any methods that are awaiting AccessTheWebAsync retrieve the length value.  
return urlContents.Length;  
} 

1 Ответ

0 голосов
/ 15 сентября 2018

ждет, делает то, что говорит, он ждет.Когда вы нажимаете await, он не переходит к вызывающему методу, он ждет, пока Todo не будет завершен.Теперь зачем использовать async/await, если оно ждет?Потому что во время этого ожидания он выполняет другую работу.Он поддерживает работу вашего интерфейса.Он обрабатывает сообщения из очереди сообщений, такие как нажатие кнопок, элементы управления рисованием, вычисление попадания курсора в какие-либо ограничивающие рамки, которые будут выделять элемент управления, и т. Д.

Ваш код сейчас полностью синхронен, поскольку вы не ожидаетеTask.Delay.Вы, вероятно, даже получаете предупреждение для каждого не ожидаемого метода.

Вот как должен выполняться этот код:

  1. Ожидание 3000 мс
  2. Возврат "возврата из асинхронной задачи"
  3. Ожидание 500 мс
  4. Печать" возврата из асинхронной задачи "
  5. Печать" завершение "

Код:

private async void btn1_Click(object sender, EventArgs e)
{
   await TestAsync();
   Console.WriteLine("terminate");
}

private async Task TestAsync()
{
   string str = await Todo();
   await Task.Delay(500);
   Console.WriteLine(str);
}

private async Task<string> Todo()
{
   await Task.Delay(3000);
   return "return from async task";
}
...