Пока ваша программа некоторое время блокируется, она возобновляет выполнение в цикле for, прежде чем результат будет возвращен с удаленного сервера.
Помните, что новый асинхронный API все еще однопоточный. Таким образом, WebClient().DownloadStringTaskAsync()
по-прежнему должен выполняться в вашем потоке до тех пор, пока запрос не будет подготовлен и отправлен на сервер, прежде чем он сможет await
и вернуть выполнение в поток вашей программы в Main ().
Я думаю, что результаты, которые вы видите, связаны с тем, что создание и отправка запроса с вашего компьютера занимает некоторое время. Сначала, когда это закончится, реализация DownloadStringTaskAsync
может ожидать завершения сетевого ввода-вывода и удаленного сервера и может вернуть вам выполнение.
С другой стороны, ваш метод RunOrdinaryTask
просто инициализирует задачу, дает ей рабочую нагрузку и сообщает о ее запуске. Тогда это возвращается немедленно. Вот почему вы не видите задержки при использовании RunOrdinaryTask
.
Вот несколько ссылок на эту тему: Блог Эрика Липперта (один из разработчиков языков), а также Первоначальное сообщение в блоге Джона Скита об этом. У Эрика есть серия из 5 постов о стиле прохождения продолжения, о чем на самом деле async
и await
. Если вы хотите понять новую функцию в деталях, вы можете прочитать сообщения Эрика о CPS и Async. В любом случае, обе ссылки выше хорошо объясняют очень важный факт:
- Асинхронный! = Параллельный
Другими словами, async
и await
не создают новых тем для вас. Они просто позволяют вам возобновить выполнение вашего обычного потока, когда вы выполняете операцию блокировки - времена, когда ваш процессор просто сидит и ничего не делает в синхронной программе, ожидая завершения какой-либо внешней операции.
Редактировать
Просто чтобы понять, что происходит: DownloadStringTaskAsync
устанавливает продолжение, затем вызывает WebClient.DownloadStringAsync
в том же потоке, а , а затем возвращает выполнение к вашему коду. Следовательно, время блокировки, которое вы видите перед началом подсчета цикла, - это время, которое требуется DownloadStringAsync
для завершения. Ваша программа с async и await очень похожа на следующую программу, которая демонстрирует то же поведение, что и ваша программа: начальный блок, затем начинается отсчет, и где-то посередине асинхронная операция завершается и печатает содержимое из запрошенный URL:
static void Main(string[] args)
{
WebClient cli = new WebClient();
cli.DownloadStringCompleted += (sender, e) => Console.WriteLine(e.Result);
cli.DownloadStringAsync(new Uri("http://www.weather.gov")); // Blocks until request has been prepared
for (int i = 0; i < 15; i++)
{
Console.WriteLine(i);
Thread.Sleep(100);
}
}
Примечание: я ни в коем случае не эксперт в этом вопросе, поэтому я могу ошибаться в некоторых моментах. Не стесняйтесь исправить мое понимание предмета, если вы считаете, что это неправильно - я только что посмотрел презентацию PDC и поиграл с CTP вчера вечером.