Я пытаюсь понять тонкости async/await в C# и портов завершения ввода-вывода в Windows, попутно пишу код для проверки своих предположений.
Насколько я понимаю, вызов WebClient.DownloadStringTaskAsync(...) заставит текущий поток зарегистрировать операцию ввода-вывода с портом завершения ввода-вывода (это, вероятно, немного расплывчато, я пока не понимаю деталей), он создаст Task<string> и продолжит выполнение кода. В какой-то момент он встретит await для данной задачи. В этот момент он вернется из текущего метода (ну, он выйдет из какой-то области, я не уверен, может ли эта область быть чем-то другим, кроме метода - мне, вероятно, следует проверить сгенерированный конечный автомат, чтобы понять эту часть) . После завершения операции ввода-вывода поток будет захвачен из пула потоков, ему будет передан результат операции ввода-вывода, и он выполнит остальную часть только что упомянутой области.
Я пытался проверить это поведение, но добрался только до этого кода С#, прежде чем что-то показалось неправильным:
class Program
{
static void Main(string[] args)
{
ThreadPool.SetMaxThreads(30, 30);
Console.WriteLine("Connection limit is {0}", ServicePointManager.DefaultConnectionLimit);
for (int i = 0; i < 30; i++)
{
FetchAsync(i);
}
Console.WriteLine("Done starting requests");
Console.ReadKey();
}
private async static void FetchAsync(int num)
{
WebClient wc = new WebClient();
string result = await wc.DownloadStringTaskAsync("http://localhost/slow/index/15");
Console.WriteLine("Done #{0}", num);
}
}
Как вы можете видеть, я использую WebClient для создания 30 запросов к веб-странице (которые, как я знаю, медленные и для ответа потребуется 15 секунд). Запустив этот код, я наблюдаю следующее поведение: через 15 секунд выполняются первые 10 запросов. Еще через 15 секунд выполняются еще 10 запросов, а еще через 15 секунд выполняются оставшиеся запросы. Таким образом, может показаться, что одновременно имеется только 10 невыполненных запросов (используя perfmon, я проверил, что вызываемое веб-приложение имеет 10 текущих запросов). Это почему? Я ожидал 30 одновременных запросов, так как установил максимальное количество потоков для пула потоков в соответствии с приведенным выше кодом.
Этот вопрос SO заставьте меня поверить, что ServicePointManager может иметь какое-то отношение к этому, но поскольку DefaultConnectionLimit всего 2, я полагаю, что связи нет.
Я понимаю, что это довольно длинное описание довольно простого вопроса. Я надеюсь, что кому-то будет легче указать, где именно мои предположения неверны.
Я запускаю это на Windows 7, 64-битной машине.
ServicePointManager, взгляните на этот вопрос, и он может немного помочь вам в пути. stackoverflow.com/questions/866350/ - person Karl-Johan Sjögren   schedule 28.10.2012Thread. - person L.B   schedule 28.10.2012ServicePointmanager.DefaultConnectionLimitна разумное число. - person L.B   schedule 28.10.2012