Поддержка асинхронного вызова Web-методов в .NET 2.0 сильно изменилась по сравнению с .NET 1.x. По своему предыдущему опыту вы можете знать, что агенты .NET 1.1 использовали методы BeginXXX/EndXXX для вызова Web-методов во вторичном потоке выполнения. Рассмотрите, например, следующие методы BeginSubtract и EndSubtract.
public System.IAsyncResult BeginSubtract(int x, int y, System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("Subtract", new object[] {x, y}, callback, asyncState);
}
public int EndSubtract (System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((int) (results[0]));
}
Хотя wsdl.exe все еще генерирует эти знакомые методы Begin/End, в .NET 2.0 они считаются устаревшими, поскольку заменены новыми методами XXXAsync.
public void SubtractAsync(int x, int y) {
this.SubtractAsync(x, y, null);
}
Новые методы XXXAsync (как и связанный с ними метод CancelAsync) работают в паре с автоматически генерируемым вспомогательным методом (являющимся перегруженной версией некоторого специального метода XXXAsync), который обрабатывает асинхронные операции, используя синтаксис событий C#. Если рассмотреть программный код агента, вы увидите, что wsdl.exe генерирует (для каждого Web-метода) пользовательский делегат, пользовательское событие и пользовательский класс "event args", чтобы получить соответствующий результат.
Теперь, когда вы лучше понимаете внутреннюю композицию генерируемого агента, давайте попытаемся его использовать. Создайте новое консольное приложение с именем CalculatorClient, добавьте в проект файл proxy.cs с помощью выбора Project->Add Existing Item из меню и добавьте ссылку на компоновочный блок System.Web.Services.dll. Затем измените метод Main так, как предлагается ниже.
class Program {
static void Main(string[] args) {
Console.WriteLine("***** Забавы c агентами WS *****\n");
// Создание агента.
CalculatorWebService ws = new CalculatorWebService;
// Синхронный вызов метода Add.
Console.WriteLine("10 + 10= {0}", ws.Add(10, 10));
// Асинхронный вызов метода Subtract с помощью
// нового подхода .NET 2.0 на основе событий.
ws.SubtractCompleted += new SubtractCompleteEventHandler(ws_SubtractCompleted);
ws.SubtractAsync(50, 45);
// Продолжение работы консоли для гарантии получения
// результата вычитания.
Console.RеаdLine;
}
static void ws_SubtractCompleted(object sender, SubtractCompletedEventArgs e) {
Console.WriteLine("Baш ответ: {0} ", e.Result);
}
}
Обратите внимание на то, что новая логика асинхронного вызова в .NET 2.0 непосредственно отображается в синтаксис событий C#, который, согласитесь, является более аккуратным по сравнению с использованием методов BeginXXX/EndXXX, интерфейса IAsyncResult и делегата AsyncCallback.
Исходный код. Проект CalculatorClient размещен в подкаталоге, соответствующем главе 25.
Утилита wsdl.exe, конечно, предлагает целый ряд аргументов командной строки, которые позволяют контролировать результат генерирования класса агента, но Visual Studio 2005 позволяет быстро сгенерировать файл агента, используя диалоговое окно Add Web Reference (Добавление Web-ссылки), которое можно вызвать из Меню Project. Как видно из рис. 26.6, в этом окне вы можете получить ссылки на существующие Web-сервисы XML, размещенные в самых разных местах.
Замечание. Диалоговое окно Add Web Reference не позволяет ссылаться на Web-сервисы XML, которые обслуживаются WebDev.WebServer.exe.
Рис. 25.6. Диалоговое окно Add Web Reference