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

Ватсон Карли

Шрифт:

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
в начале и в конце метода:

// зарегистрировать клиентский приемник на сервере — подписаться

// на событие

obj.Status += new StatusEvent(sink.StatusHandler);

obj.LongWorking(5000);

Теперь мы более не заинтересованы в получении событий с сервера и отменяем подписку на событие. Следующий раз при вызове

LongWorking
никакие события не будут получены.

// отменить подписку на событие

obj.Status -= new StatusEvent(sink.StatusHandler);

obj.LongWorking(5000);

Console.WriteLine("Hit to exit");

Console.ReadLine;

}

 }

}

Конфигурационный файл клиента

Конфигурационный файл для клиента —

client.exe.config
является почти таким же конфигурационным файлом, как и для активированных клиентом объектов. Различие можно найти в определении номера порта для канала. Поскольку сервер должен соединяться с клиентом через известный порт, то необходимо определить номер порта для канала как атрибут элемента
<channel>
. Не требуется определять раздел
<service>
для класса
EventSink
, так как экземпляр этого класса будет создаваться клиентом локально с помощью оператора new. Сервер не получает доступ к этому объекту по его имени, вместо этого он получит маршализированную ссылку на экземпляр:

<configuration>

 <system.runtime.remoting>

<application name="Client">

<client url="http://localhost:6791/CallbackSample">

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

</client>

<channels>

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

<channels>

</application>

 </system.runtime.remoting>

</configuration>

Выполнение программы

Мы видим результирующий вывод на сервере: конструктор удаленного объекта вызывается один раз, так как имеется активированный клиентом объект. Затем происходит вызов метода

LongWorking
и порождение события на клиенте. Следующий запуск метода
LongWorking
не порождает событий, так как клиент уже отменил регистрацию своего интереса к событию:

В выводе клиента видно, что события достигают его по сети:

Контексты вызова

Активированные клиентом объекты могут сохранять состояние для определенного клиента. Для активированных клиентом объектов на сервере требуются ресурсы. Для активированных сервером объектов

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

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

Можно присвоить данные контексту вызова с помощью метода

CallContext.SetData
. Класс с объекта, который используется в качестве данных для метода
SetData
, должен реализовать интерфейс
ILogicalThreadAffinative
. Эти данные можно получить снова в том же логическом потоке выполнения (но, возможно, в другом физического потоке выполнения) с помощью
CallContext.GetData
.

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

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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