Проблема связи между AppDomain

Я занимаюсь разработкой службы Windows на С#.

При запуске этой службы предоставляется набор путей файла конфигурации. Для каждого из этих файлов служба будет разворачивать AppDomain с использованием файла в качестве ConfigurationFile и папки этого файла как ApplicationBase. Каждая папка будет иметь папку "bin", которая устанавливается как PrivateBinPath.

В папке "bin" в этих папках содержится небольшая сборка, которая совместно используется службой, эта сборка содержит интерфейс IServiceHost. Также известно имя типа и имя сборки класса, реализующего интерфейс IServiceHost.

Весь метод CreateServiceHost выглядит следующим образом: -

    public static IServiceHost CreateServiceHost(string configPath, string entryAssembly, string entryType)
    {
        IServiceHost host;

        AppDomainSetup setupInfo = new AppDomainSetup();
        setupInfo.ApplicationBase = Path.GetDirectoryName(configPath);
        setupInfo.PrivateBinPath = Path.Combine(setupInfo.ApplicationBase, "bin");
        setupInfo.ShadowCopyFiles = "true";
        setupInfo.ConfigurationFile = configPath;

        AppDomain appDomain = AppDomain.CreateDomain("Service for: " + setupInfo.ApplicationBase, AppDomain.CurrentDomain.Evidence, setupInfo);


        object objHost = appDomain.CreateInstanceFromAndUnwrap(Path.Combine(setupInfo.PrivateBinPath, entryAssembly), entryType);
        host = (IServiceHost)objHost;

        return host;
    }

Интерфейс IServiceHost невероятно сложный: -

public interface IServiceHost
{
    void Start();
    void Stop();
}

Служба OnStart содержит что-то вроде этого: -

private List<IServiceHost> serviceHosts = new List<IServiceHost>();

protected override void OnStart(string[] args)
{
    foreach (string configPaths in GetConfigPaths())
    {
        IServiceHost host = ServiceHostLoader.CreateServiceHost(configPath);
        serviceHosts.Add(host);
        host.Start();
    }
}

OnStop одинаково прямолинейный (теперь, чтобы все упростить, IServiceHost.Stop блокирует вызовы).

protected override void OnStop()
{
    foreach (IServiceHost host in serviceHosts)
    {
        host.Stop();
    }
}

Это все достаточно просто и отлично работает при тестировании на машинах разработки. Однако в QA я получаю исключения, когда он остановлен. Когда в развитии мы закручиваем вещи только на короткий период, все кажется, что все работает нормально. Однако в QA услуга останавливается только каждые 24 часа. В этом случае он последовательно не может остановиться правильно.

Вот пример того, что заканчивается в журнале событий: -

Тип события: событие ошибки Источник: событие службы рабочего пространства Категория: нет КОД события: 0 Дата: 11/03/2011 Время: 08:00:00 Пользователь: нет данных Компьютер: QA-IIS-01 Описание: Не удалось остановить службу. System.Runtime.Remoting.RemotingException: объект '/50e76ee1_3f40_40a1_9311_1256a0375f7d/msjxeib0oy+s0sog1mkeikjd_2.rem' был отключен или не существуют на сервере.

Трассировка стека сервера: at System.Runtime.Remoting.Channels.ChannelServices.CheckDisconnectedOrCreateWellKnownObject(Шеззаде msg) при System.Runtime.Remoting.Channels.ChannelServices.SyncDispatchMessage(Шеззаде MSG)

Исключение, сброшенное в [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(Шеззаде reqMsg, IMessage retMsg) в System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData & msgData, тип Int32) при MyOrg.Service.IServiceHost.Stop() в MyOrg.Workspace.Service.MyAppService.OnStop() в System.ServiceProcess.ServiceBase.DeferredStop()

Дополнительные сведения см. в справке и Центр поддержки http://go.microsoft.com/fwlink/events.asp.

Теперь для тестовых целей фактический IServiceHost просто записывает записи в журнал событий в виде сердечного ритма и записи, указывающие начало и остановку, и я только разворачиваю один AppDomain.

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

Может ли кто-нибудь объяснить, почему это происходит, или предложить лучший способ для домена по умолчанию запрашивать сгенерированные домены в порядке очереди?

Ответы

Ответ 1

Удар в темноте. Срок действия лизинга на удаленном объекте истекает? Посмотрите MarshalByRefObject.InitializeLifetimeService. Чтобы сделать объект постоянным, просто переопределите и верните null.

public override object InitializeLifetimeService()
{
    // returning null here will prevent the lease manager
    // from deleting the object.
    return null;
}