Чтение онлайн

ЖАНРЫ

C# для профессионалов. Том II

Ватсон Карли

Шрифт:

 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);

e.Message = "Message for Client: LongWorking Ending"; // породить
событие окончания

if (Status != null) {

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

Status(this, e);

}

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

 }

}

Аргументы событий

Мы видели в классе

RemoteObject
, что класс
StatusEventArgs
используется как аргумент для делегата. С помощью атрибута
[Serializable]
экземпляр этого класса может передаваться от сервера клиенту. Мы используем простое свойство типа string для пересылки клиенту сообщения:

[Serializable]

public class StatusEventArgs {

 public StatusEventArgs(string m) {

message = m;

 }

 public string Message {

get {

return message;

}

set {

message = value;

}

 }

 private string message;

}

Сервер

Сервер реализуется внутри консольного приложения. Мы ожидаем только, чтобы пользователь завершил работу сервера после чтения конфигурационного файла и настройки канала и удаленного объекта:

using System;

using System.Runtime.Remoting;

namespace Wrox.ProfessionalCSharp {

 class Server {

static void Main(string[] args) {

RemotingConfiguration.Configure("Server.exe.config");

Console.WriteLine("Hit to exit");

Console.ReadLine;

}

 }

}

Конфигурационный файл сервера

Способ создания конфигурационного файла сервера

Server.exe.config
мы уже обсуждали. Существует только один важный момент. Так как клиент сначала регистрирует обработчик событий и после этого вызывает удаленный метод, то удаленный объект должен сохранять состояние клиента. Можно использовать с событиями объекты
SingleCall
, поэтому класс
RemoteObject
конфигурируется в виде активированного клиентом типа:

<configuration>

 <system.runtime.remoting>

<application name="CallbackSample">

<service>

<activated type="Wrox.ProfessionalCSharp.RemoteObject, RemoteObject" />

</service>

<channels>

<channel type="System.Runtime.Remoting.Channels.Http.HttpChannel, System.Runtime.Remoting" port="6791" />

</channels>

</application>

 </system.runtime.remoting>

</configuration>

Приемник

событий

Приемник событий реализует обработчик

StatusHandler
, который определен в делегате. Как ранее отмечалось, метод может иметь только входные параметры и возвращать только
void
. Это в точности соответствует требованиям методов
[OneWay]
, как мы видели ранее при рассмотрении асинхронной удаленной работы.
StatusHandler
будет вызываться асинхронно. Класс
EventSink
должен также наследовать из класса
MarshalByRefObject
, чтобы сделать его удаленным, так как он будет вызывать с сервера удаленным образом:

using System;

using System.Runtime.Remoting.Messaging;

namespace Wrox.ProfessionalCSharp; {

 public class EventSink MarshalByRefObject {

public EventSink { }

[OneWay]

public void StatusHandler(object sender, StatusEventArgs e) {

Сonsole.WriteLine("EventSink: Event occurred: " + e.Message);

}

 }

}

Клиент

Клиент читает конфигурационный файл клиента с помощью класса

RemotingConfiguration
. Так было со всеми клиентами, которые создавались до сих пор. Клиент создает локально экземпляр удаленного класса приемника
EventSink
. Метод, который должен вызываться из удаленного объекта на сервере, передается в удаленный объект:

using System;

using System.Runtime.Remoting;

namespace Wrox.ProfessionalCSharp {

 class Client {

static void Main(string[] args) {

RemotingConfiguration.Configure("Client.exe.config");

Различие начинается здесь. Мы должны создать локально экземпляр удаленного класса приемника

EventSink
. Так как этот класс не будет конфигурироваться элементом
<client>
, то его экземпляр создается локально. Затем мы получаем экземпляр класса удаленного объекта
RemoteObject
. Этот класс конфигурируется в элементе
<client>
, поэтому его экземпляр создается на удаленном сервере:

EventSink sink = new EventSink;

RemoteObject obj = new RemoteObject;

Теперь можно зарегистрировать метод обработчика объекта

EventSink
на удаленном объекте.
StatusEvent
является именем делегата, который был определен на сервере. Метод
StatusHandler
имеет те же самые аргументы, которые определены в
StatusEvent
.

Вызывая метод

LongWorking
, сервер будет делать обратный вызов в методе
StatusHandler
в начале и в конце метода:

Поделиться с друзьями: