【问题标题】:Why does a windows service create multiple instances of a service host为什么一个windows服务会创建一个服务主机的多个实例
【发布时间】:2013-10-22 06:48:39
【问题描述】:

我在 Windows 服务中托管一个简单的 WCF 服务。 WCF 服务本身会创建 TextWriterTraceListener,它将检测数据记录到其中。

奇怪的是,即使windows服务没有重启,它似乎还在不断创建新的日志文件,并且正在将相同的日志条目写入多个文件。

上述行为只有在 MyService 的构造函数被多次触发时才会发生,基本上是每次客户端连接到服务时。我的不理解和希望是它只会创建一个 MyServiceBase 实例,因此只创建一个 MyService 实例(每次 Windows 服务启动时)。

当然,我可以解决这个问题并检查有多少侦听器已添加到 Trace,但我想了解发生了什么。

代码如下:

var ServicesToRun = new ServiceBase[] 
            { 
                new MyServiceBase() 
            };
        ServiceBase.Run(ServicesToRun);

public partial class MyServiceBase : ServiceBase
{
    ServiceHost _serviceHost;

    public MyServiceBase()
    {
        InitializeComponent();
    }


    protected override void OnStart(string[] args)
    {
        _serviceHost = new ServiceHost(typeof(MyService));            
        _serviceHost.Open();

    }

    protected override void OnStop()
    {
        if (_serviceHost != null)
        {
            _serviceHost.Close();
        }
        _serviceHost = null;
    }        
}

 public MyService()
    {         
        _fileListner = new TextWriterTraceListener(string.Format(@"{0}\Trace{1}.log", logDir, DateTime.Now.Ticks));
        Trace.Listeners.Add(_fileListner);
        WriteTraceMessage(string.Format("Service started {0}", DateTime.Now), new Guid("71961817-CB62-410f-AB44-43BFCE246847"));
    }

【问题讨论】:

  • 我还要指出问题标题不准确。有一个 single 服务主机正在创建 service 类的多个实例。

标签: wcf


【解决方案1】:

MyService 实例的创建方式和时间由 WCF 功能控制,例如 InstanceContextMode(它是 ServiceBehaviourAttribute 的一部分):

使用InstanceContextMode 属性指定何时创建新服务对象。因为服务对象不直接连接到通信通道,所以服务对象的生命周期独立于客户端和服务应用程序之间的通道的生命周期。默认值PerSession 指示服务应用程序在客户端和服务应用程序之间建立新的通信会话时创建新的服务对象。同一会话中的后续调用由同一对象处理。

Sessions, Instancing and Concurrency 中还有很多值得阅读的内容。


我的不理解和希望是它只会创建一个 MyServiceBase 的实例,因此只会创建一个 MyService 的实例

但请注意,在您的 OnStart 方法中,您并没有创建新的 MyService 对象 - 您将 type 传递给 ServiceHost,因为主机随后使用用于确定生命周期的 WCF 属性(或配置)。

【讨论】:

  • 感谢您的解释。设置 InstanceContextMode = InstanceContextMode.Single 就可以了。
【解决方案2】:

您使用类型启动服务主机。

_serviceHost = new ServiceHost(typeof(MyService));    

这意味着服务主机必须创建一个实例。它将使用其他答案中提到的参数来执行此操作。如果您不希望服务主机为您创建实例,您可以给它一个实例以供自己使用:

_serviceHost = new ServiceHost(new MyService());    

服务主机将使用此实例来处理所有调用。不过,您可能希望先将其放入变量中。

【讨论】:

    【解决方案3】:

    默认情况下,实例上下文模式将设置为每个会话。因此,当请求到来时,它将创建一个新的服务实例。如果您想每次调用只创建一个实例,则设置实例上下文模式=每次调用。如果您只想为整个应用程序创建一个实例,请设置实例上下文模式=单个。

    供您参考,请检查此链接: http://wcftutorial.net/Per-Call-Service.aspx

    【讨论】:

    猜你喜欢
    • 2011-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-19
    • 2014-10-12
    相关资源
    最近更新 更多