Inter-AppDomain通信问题

时间:2011-03-11 16:53:24

标签: c# .net windows-services remoting appdomain

我一直在用C#开发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小时停止一次。在这种情况下,它始终无法正确停止。

以下是事件日志中最终结果的示例: -

  

事件类型:错误事件   来源:工作区服务活动   类别:无事件ID:0   日期:11/03/2011时间:08:00:00   用户:N / A计算机:QA-IIS-01   描述:无法停止服务。   System.Runtime.Remoting.RemotingException:   宾语   '/50e76ee1_3f40_40a1_9311_1256a0375f7d/msjxeib0oy+s0sog1mkeikjd_2.rem'   已断开连接或未连接   存在于服务器上。

     

服务器堆栈跟踪:at   System.Runtime.Remoting.Channels.ChannelServices.CheckDisconnectedOrCreateWellKnownObject(即时聊天   msg)at   System.Runtime.Remoting.Channels.ChannelServices.SyncDispatchMessage(即时聊天   MSG)

     

在[0]处重新抛出异常:at   System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(即时聊天   reqMsg,IMessage retMsg)at   System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&安培;   msgData,Int32类型)at   MyOrg.Service.IServiceHost.Stop()   在   MyOrg.Workspace.Service.MyAppService.OnStop()   在   System.ServiceProcess.ServiceBase.DeferredStop()

     

有关详细信息,请参阅“帮助和”   支持中心在   http://go.microsoft.com/fwlink/events.asp

现在出于测试目的,实际的IServiceHost只是将条目作为心跳发布到事件日志中,条目表示启动和停止,我只是在启动单个AppDomain。

似乎随着时间的推移,主服务默认应用域中IServiceHost的实施者的远程代理已与生成的域中的另一端失去联系。

任何人都可以解释为什么会发生这种情况,或者为默认域提供更好的方法来要求生成的域以整齐的方式关闭吗?

1 个答案:

答案 0 :(得分:25)

在黑暗中刺伤。远程对象的生命周期租约是否到期?看看MarshalByRefObject.InitializeLifetimeService。要使对象持久化,只需覆盖并返回null

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