Вход/Регистрация
C# для профессионалов. Том II
вернуться

Ватсон Карли

Шрифт:

ar.AsyncWaitHandle.WaitOne;

if (ar.IsCompleted) {

greeting = d.EndInvoke(ar);

}

Console. WriteLine(greeting);

}

 }

}

О событиях, делегатах и асинхронных методах можно прочитать в главе 6.

Атрибут OneWay

Метод, который возвращает

void
и имеет только входящие параметры, может быть помечен атрибутом
OneWay
. Атрибут
OneWay
делает метод автоматически асинхронным независимо от того, как вызывает его клиент. Добавление метода
TakeAWhile
в класс удаленного объекта
RemoteHello
соответствует созданию метода "породить и забыть". Если клиент вызывает его через прокси, то прокси немедленно возвращает управление клиенту. На сервере метод заканчивается немного позже:

[OneWay]

public Void TakeAWhile(int ms) {

 Console.WriteLine("TakeAWhile started");

 System.Threading.Thread.Sleep(ms);

 Console.WriteLine("TakeAWhile finished");

}

Удаленное выполнение и события

С помощью .NET Remoting не только клиент может вызывать методы на удаленном объекте через сеть, но и сервер может также вызывать методы на клиенте. Для этого используются детали механизма основных свойств языка: делегаты и события.

В принципе это простая архитектура. Сервер имеет объект, который может вызывать клиент, а клиент имеет объект, который в свою очередь может вызывать сервер:

□ Удаленный объект на сервере должен объявить внешнюю функцию (делегата) с сигнатурой метода, который клиент будет реализовывать в обработчике.

□ Аргументы, которые передаются клиенту с функцией-обработчиком, должны быть маршализуемыми. Поэтому все посылаемые клиенту данные должны быть сериализуемыми.

□ Удаленный объект должен также объявить экземпляр функции делегата, модифицированный ключевым словом event. Клиент будет использовать его для регистрации обработчика.

□ Клиент должен создать объект приемника с методом обработчика, имеющий такую же сигнатуру, как и определенный делегат, и должен зарегистрировать объект приемника для события на удаленном объекте.

Чтобы понять это, рассмотрим пример. Создадим пять классов для всех частей обработки событий в .NET Remoting. Класс

Server
является удаленным сервером, таким как один из тех, которые уже до этого встречались. Класс
Server
будет создавать канал на основе информации из конфигурационного файла и регистрировать удаленный объект, который реализуется в классе
RemoteObject
в удаленной среде выполнения. Удаленный объект объявляет аргументы делегата и порождает события в зарегистрированных функциях обработчика. Аргумент, который передается в функцию обработчика, имеет тип
StatusEventArgs
. Класс
StatusEventArgs
должен быть сериализуемым, поэтому его можно маршализовать клиенту.

Класс

Client
представляет клиентское приложение. Этот класс создает экземпляр класса
EventSink
и регистрирует метод
StatusHandler
этого класса как обработчика для делегата в удаленном объекте.
EventSink
должен быть удаленным объектом, подобным классу
RemoteClass
, так как этот класс также будет вызываться через сеть.

Удаленный объект

Класс удаленного объекта реализуется в файле

RemoteObject.cs
. Класс удаленного объекта должен выводиться из
MarshalByRefObject
так, как было показано в предыдущих примерах. Чтобы сделать возможным для клиента регистрацию обработчика событий, который вызывается из удаленного объекта, необходимо объявить внешнюю функцию с помощью ключевого слова
delegate
. Мы объявляем делегата
StatusEvent
с двумя аргументами:
sender
(поэтому клиент знает об объекте, который порождает событие) и переменную типа
StatusEventArgs
. В класс аргумента помещаем всю дополнительную информацию, которую необходимо послать клиенту.

Метод, который реализуется на стороне клиента, требует строгих ограничений. Он может иметь только входные параметры, возвращаемые типы, при этом параметры

ref
и
out
недопустимы; а типы аргументов должны быть либо
[Serializable]
, либо удаленными (выводимыми из
MarshalByRefObject
):

public delegate void StatusEvent(object sender, StatusEventArgs e);

public class RemoteObject : MarshalByRefObject {

Внутри класса

RemoteObject
объявляется экземпляр функции делегата
Status
, модифицированный ключевым словом
event
. Клиент должен добавить обработчик событий в событие
Status
, чтобы получить статусную информацию из удаленного объекта:

public class RemoteObject : MarshalByRefObject {

 public RemoteObject {

Console.WriteLine("RemoteObject constructor called");

 }

 public event StatusEvent Status;

В методе

LongWorking
проверяется, что обработчик событий регистрируется прежде, чем событие порождается с помощью
Status(this, е)
. Чтобы удостовериться, что событие порождается асинхронно, мы получаем событие в начале метода перед выполнением
Thread.Sleep
и после
Sleep
:

 public void LongWorking(int ms) {

Console.WriteLine("RemoteObject: LongWorking Started");

StatusEventArgs e = new StatusEventArgs("Message for Client: LongWorking Started");

// породить событие

if (Status != null) {

Console.WriteLine("RemoteObject: Firing Starting Event");

Status(this, e);

}

System.Threading.Thread.Sleep(ms);

  • Читать дальше
  • 1
  • ...
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: