WCF,ServiceHost - CreateChannel,不要创建新的远程实例

时间:2012-01-26 21:29:36

标签: c# .net wcf

我得到了一个通常的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;
    }
} 

从这段代码中,我想,创建了一个“内核”实例,因为我只运行了一次该服务。

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

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

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

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

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

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

此致 INVA

1 个答案:

答案 0 :(得分:3)

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

当然,您可以使用InstanceContextMode之类的内容来控制这一点(PerSession是默认设置 - 至少在支持它的绑定上,PerCall推荐的最佳做法,以及<{1}}是Singleton)和服务上的Single设置。

您可以在config中定义,也可以直接在服务类上定义。

ConcurrencyMode

请参阅MSDN documentation on WCF Sessions, Instancing and Concurrency,详细了解所有细节。另请阅读Juval Lowy撰写的优秀MSDN杂志文章Discover Mighty Instance Management Techniques For Developing WCF Apps,这是一个很好的资源!

如果您确实将服务类切换为单身([ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] public class CalculatorService : ICalculatorInstance { ... } ),则需要注意两个权衡因素:

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

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