我一直在用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
的实施者的远程代理已与生成的域中的另一端失去联系。
任何人都可以解释为什么会发生这种情况,或者为默认域提供更好的方法来要求生成的域以整齐的方式关闭吗?
答案 0 :(得分:25)
在黑暗中刺伤。远程对象的生命周期租约是否到期?看看MarshalByRefObject.InitializeLifetimeService。要使对象持久化,只需覆盖并返回null
。
public override object InitializeLifetimeService()
{
// returning null here will prevent the lease manager
// from deleting the object.
return null;
}