//static void ComparePages() //{ // var wc = new WebClient(); // string s1 = wc.DownloadString("http://www.rsdn.ru"); // string s2 = wc.DownloadString("http://rsdn.ru"); // Console.WriteLine(s1 == s2 ? "Одинаковые" : "Различные"); //} static void ComparePages() { // создаем два экземпляра делегата DownloadString: Func <string, string> download1 = new WebClient().DownloadString; Func <string, string> download2 = new WebClient().DownloadString; // Стартуем загрузку: IAsyncResult cookie1 = download1.BeginInvoke("http://www.rsdn.ru", null, null); //BeginInvoke нужны два дополнительных параметра – метод обратного вызова и объект //с данными; обычно в них нет необходимости и можно передать в них null. //BeginInvoke возвращает объект IASynchResult, используемый как cookie для вызова EndInvoke. //У объекта IASynchResult есть также свойство IsCompleted, которое можно использовать //для проверки завершения операции. IAsyncResult cookie2 = download2.BeginInvoke("http://rsdn.ru", null, null); // Выполняем какие-то вычисления: double seed = 1.23; for (int i = 0; i < 1000000; i++) { seed = Math.Sqrt(seed + 1000); } Thread.Sleep(5000); // Получаем результат загрузки, ожидая в случае необходимости. string s1 = download1.EndInvoke(cookie1); //Если при исполнении асинхронного метода возникает необработанное исключение, //оно будет повторно сгенерировано при вызове EndInvoke. //Это позволяет аккуратно передавать исключения вызывающему коду string s2 = download2.EndInvoke(cookie2); //Даже если вызываемый асинхронно метод не возвращает никакого значения, //чисто технически все равно необходимо вызывать EndInvoke. Однако на практике //возможны варианты. MSDN выдает противоречивые рекомендации на этот счет. //Если не вызывается EndInvoke, то необходимо разрешить проблему //обработки исключений в вызываемом методе. Console.WriteLine(s1 == s2 ? "Одинаковые" : "Различные"); }