WCF服务的PerCall InstanceContextMode行为

时间:2014-11-15 11:02:22

标签: c# .net wcf basichttpbinding instancecontextmode

我有一个WCF服务,使用basicHttpBinding公开ServiceContract,因此根据我的理解 InstanceContextMode 将设置为PerCall(因为basicHttpBinding不支持会话),ConcurrenyMode将设置为Single。

这个WCF的客户端是一个Windows服务,它同时在服务上调用4个不同的操作,在我们使用单例类的服务中,并且静态变量很少。我们遇到了一个问题,即错误的值传递给某些DB存储过程。

使用PerCall InstanceContextMode和Single并发模式,我理解为每个调用创建一个新的服务instacne,因此我认为即使在服务实现和静态中有一些单例类(我们没有使它成为线程安全)变量所有对象都将被销毁,但我们观察到运行一个SQL分析器,旧的值传递给DB。

我们用一种3层架构编写了我们的WCF服务代码,我的意思是ServiceClass,BusinessLogicLayer和DataAccessLayer,当我们说服务实例在客户端请求完成后被销毁时,PerCall设置为instanceContextMode,是不是意味着我们销毁ServiceClass,BusinessLogicLayer和DataAccessLayer中的所有对象?

请帮助我理解可能出现的问题

3 个答案:

答案 0 :(得分:0)

InstanceContextMode PerCall 表示您的服务的新类实例化每次调用。 AppDomain中的静态变量不会被重置。只要您的AppPool不被回收,它们将保持在服务呼叫之间。

从代码中删除所有静态内容,包括单例。无论如何,他们从不属于你的建筑。

答案 1 :(得分:0)

许多WCF请求共享相同的AppDomain。静态变量是每个AppDomain。 WCF对这些变量没有任何作用(实际上它甚至不能发现它们存在)。你有责任维护它们。

WCF不会销毁任何对象,因为 WCF既不明白它们的含义,也不知道它们存在

您提到的设置仅与服务对象相关。

关于有状态服务器应用程序的常见建议:您在这里处理不良做法。您需要确保线程安全。如果工作进程关闭(部署,自动重启,服务器重启,应用程序错误导致进程崩溃,电源丢失,硬件故障......),您的数据将丢失。

答案 2 :(得分:0)

尽管以任何方式限制静态变量都需要保护线程安全,这是最佳实践。在服务停止/应用程序池回收之前,不会销毁静态变量。

对于不建议用于分布式Web场的数据使用静态变量,因为这些变量在故障转移时不安全。

Visual Studio 2012及更高版本附带内存分析器。但是简单的事情可以使用对象构造函数中的计数器(仅在测试时)来完成,这可以判断是否在每个请求上创建了新实例。

   [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall,ConcurrencyMode=ConcurrencyMode.Single)]
public class TestServiceWithStaticVars : ITestServiceWithStaticVars
{
   static int instanceCount = 0;
    public TestServiceWithStaticVars()
    {
        Interlocked.Decrement(ref instanceCount);
    }
    public string GetInstanceCount()
    {
        return string.Format("You have created {0} instance", instanceCount);
    }

让您知道更好的实例计数器是否可以轻松使用。

[编辑]因为我现在无法发表评论。

重新分配静态变量将采用您所说的新值。静态变量被加载到HighFrequencyHeap中以便频繁访问。有关详细信息http://www.codeproject.com/Articles/15269/Static-Keyword-Demystified