Почему время ожидания объекта C # Remoting, даже если Lifetime возвращает значение NULL? - PullRequest
9 голосов
/ 26 мая 2011

это последнее средство после многодневного поиска в Google, чтобы попытаться найти окончательный ответ на мой вопрос.

Я создал службу Windows, форму Windows и объект Remoting (все в C #). Я использую объект Remoting для связи между службой и формой, используя события.

Вот упрощенный пример типичного взаимодействия между объектами:

  • AdminForm вызывает RemoteObject's метод RequestLoadForm ()
  • RemoteObject запускает событие, которое AdminService ожидает для
  • AdminService получает предупреждение о событии и вызывает LoadFormData (строковые данные) для RemoteObject
  • RemoteObject запускает событие, которое AdminForm прослушивает
  • AdminForm получает предупреждение о событии и может использовать строковые данные для установки значений в элементах управления AdminForm

Все это прекрасно работает, все прекрасно взаимодействует в течение первых 5 минут или около того. После этого связь между объектами как-то разорвана, и я больше не могу общаться между объектами.

Первая попытка исправить проблему состояла в том, чтобы переписать метод InitializeLifetimeService, чтобы он возвратил ноль. Это не помогло (хотя и может помочь избежать проблем с арендой в будущем).

Вторая попытка состояла в том, чтобы сделать AdminForm и AdminService ISponsors RemoteObject и настроить их на возобновление аренды объекта. Еще раз не решил проблему.

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

Это ошибка, которая появляется после простоя соединения в течение> 5 минут:

Исключение System.Runtime.Remoting.RemotingException не было обработано кодом пользователя
Сообщение = "Запрошенная служба не найдена"
Источник = "system.runtime.remoting"

Теперь странная вещь в том, что это происходит на стороне AdminService . AdminForm вызывает метод для RemoteObject штраф. Это вызывает событие, а затем AdminService видит это событие и пытается вызвать метод LoadFormData (строковые данные) RemoteObject , и именно здесь генерируется исключение.

Я полностью исчерпан поиском в Google, так как не могу найти то, что мне нужно, чтобы это исправить.

Ответы [ 5 ]

3 голосов
/ 01 октября 2014

У меня довольно похожая проблема.Надеюсь, что следующие наблюдения и решения подойдут для тех, у кого есть аналогичная проблема.

Наличие объекта A, связывающегося с объектом B через домен приложения, в то время как объект B будет вызывать объект A через некоторые обработчики событий.Оба объекта A и B наследуются от MarshalByRefObject, чтобы разрешить взаимный вызов через домен приложения.

Переопределение объекта B InitializeLifeTimeService возвращает нулевое значение для бесконечной аренды.Тем не менее, соединение все равно истекло примерно через 5 минут (без учета начального времени аренды по умолчанию) после запуска программы.

Важным наблюдением является то, что вызов от объекта A все равно будет выполнен успешно, но когда объект B обратный вызовисключение - повышение объекта B. Очевидно, что истек срок действия соединения для прокси обратного вызова объекта A, а не наоборот, как мы думали.

Следовательно, быстрый ответ, убедитесь, что оба объекта Aи B переопределяет InitializeLifeTimeService, чтобы возвратить нуль.Это решит проблему, по крайней мере, в моем случае.

Просто некоторые дополнительные материалы, когда срок действия соединения истекает, это не обязательно означает, что связанный объект является сборщиком мусора.По истечении срока аренды прокси отключается, но фактический объект все еще может присутствовать в соответствующем домене приложения.Если вы сохраняете равным истечению срока аренды для объекта, являющегося GC'd, то это может помешать вам увидеть всю картину.

2 голосов
/ 31 августа 2011

должно быть переопределено:

public override object InitializeLifetimeService(){
  return null;
}
1 голос
/ 03 сентября 2011

Вы можете установить статические свойства в System.Runtime.Remoting.Lifetime.LifetimeServices на стороне сервера:

System.Runtime.Remoting.Lifetime.LifetimeServices.LeaseTime = TimeSpan.MaxValue;

но я предпочитаю использовать лизинг / спонсоров (на стороне клиента)

http://msdn.microsoft.com/en-us/library/6tkeax11.aspx

MarshalByRefObject obj = remotingObject as MarshalByRefObject;
ILease lease = (ILease)obj.GetLifetimeService();
MyClientSponsor sponsor = new MySponsor();
lease.Register(sponsor);

если у вас есть другие проблемы с сортировкой, используйте пространство имен System.Runtime.Remoting.Services.TrackingServices http://msdn.microsoft.com/en-us/library/system.runtime.remoting.services.trackingservices.aspx

0 голосов
/ 30 января 2018

У этого может быть несколько причин.

  • Возможно, вы переопределяете InitializeLifetimeService на неправильном объекте. Найдите в своем исходном коде все упоминания MarshalByRef и внимательно посмотрите на каждый из них.

  • Бесконечная аренда длится только до выгрузки домена приложения. Найдите в своем исходном коде все упоминания Unload и дайте каждому, который выгружает любой домен приложений, длинный, пристальный взгляд.

  • Домен приложений мог быть перезагружен с завершением процесса, таким как перезапуск службы Win32. Он также может быть выгружен с помощью стороннего кода, если ваш сервер развернут на каком-либо сервере приложений, а некоторые операции развертывания или восстановления после ошибки запускают перезагрузку; изучить сторонние журналы, чтобы найти доказательства этого.

  • Добавьте достаточное количество журналов и внимательно изучите трассировки стека исключений, чтобы быть полностью уверенным, что вы не обращаетесь к стороннему объекту сервера (возможно, через свой собственный объект сервера бесконечной аренды) или к более старой версии вашего собственного кода, загруженного от того, кто знает, где, так что исследование исходного кода выше может пропустить его.

Я только что закончил исследование инцидента, который оказался комбинацией первого и последнего элемента в моем списке.

0 голосов
/ 26 мая 2011

Вы должны перезаписать метод InitializeLifeTimeService () , а не GetLifetimeService () , чтобы вернуть ноль.

 public object InitializeLifetimeService(){
   return null;
 }

Тогда объект удаления должен иметь бесконечный срок жизни.

...