WCF,ServiceHost-CreateChannel,don';t创建新的远程实例

本文关键字:程实例 实例 创建 don ServiceHost-CreateChannel WCF | 更新日期: 2023-09-27 18:21:36

我得到了一个常见的WCF服务,设置如下:

private ServiceHost serviceHost = null;
protected override void OnStart(string[] args)
{
    if (serviceHost != null)
        serviceHost.Close(); 
    Uri[] baseAddress = new Uri[]{
    new Uri("net.pipe://localhost")};
    string PipeName = "DatabaseService";
    serviceHost = new ServiceHost(typeof(Kernel), baseAddress); // Kernel implements IDatabase
    serviceHost.AddServiceEndpoint(typeof(IDatabase), new NetNamedPipeBinding(), PipeName);
    serviceHost.Open();
}
protected override void OnStop()
{
   if (serviceHost != null && serviceHost.State != CommunicationState.Closed)
    {
        serviceHost.Close();
        serviceHost = null;
    }
} 

我想,从这段代码中,创建了一个"Kernel"实例,因为我只运行过一次这个服务。

我使用ChannelFactory创建了一个代理对象,如下所示:

pipeFactory = new ChannelFactory<IDatabase>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/DatabaseService"));
m_Database = pipeFactory.CreateChannel();

我不得不说,我的内核实例访问一个本地文件,因此,我只获得一个此类的物理实例是非常重要的。我希望我的服务能解决这个问题,但我的问题来了。

当服务正在运行并且创建了一个通道并处于活动状态时,第二个客户端也会出现并想要创建一个通道。这可以正常工作,但如果我开始使用代理对象,就会抛出FaultException,因为我的Kernel类的第二个实例已经创建。

因此,我猜测Kernel类的一个实例是由每个CreateChannel调用创建的。

是否可以避免创建新实例,并在调用CreateChannel时始终返回对单个内核类实例的引用?

谨致问候,inva

WCF,ServiceHost-CreateChannel,don';t创建新的远程实例

是的,默认情况下,WCF使用每个会话或每个调用的调用约定,例如,来自客户端的每个传入服务请求都会获得服务(实现)类的一个新的独立实例。

当然,您可以使用InstanceContextModePerSession是默认设置,至少在支持它的绑定上是这样)、PerCall是推荐的最佳实践,Single是Singleton)和服务上的ConcurrencyMode设置来控制这一点。

您可以在配置中定义这些,也可以直接在服务类上定义。

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] 
public class CalculatorService : ICalculatorInstance 
{ 
    ...
}

请参阅有关WCF会话、实例化和并发的MSDN文档,以获得对所有详细信息的详尽解释。另请阅读MSDN杂志上Juval Lowy的文章《发现开发WCF应用程序的强大实例管理技术》,这是一篇非常棒的资源!

如果您确实将服务类切换为单例(InstanceContextMode=InstanceContextMode.Single),则需要注意两个权衡:

  • 或者将ConcurrencyMode定义为Single,这实际上意味着一次只能处理一个请求;请求将被序列化,也就是说,如果处理请求需要相当长的时间,那么后续的请求将不得不开始等待,并且可能会超时

  • 另一种选择是将ConcurrencyMode设置为Multiple,这样您的singleton服务类就可以同时处理多个请求;但这也意味着,您必须以完全线程安全的方式编写服务类,并且您需要同步和保护对共享数据成员的任何并发访问-这通常是一个非常棘手且难以正确执行的编程练习