4

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

这个 WCF 的客户端是一个 windows 服务,它同时调用服务上的 4 个不同的操作,在服务中我们使用了一个单例类,并且几乎没有静态变量。我们一直面临一个问题,即错误的值被传递给某些 DB 存储过程。

使用 PerCall InstanceContextMode 和 Single 并发模式,我了解为每次调用创建的新服务实例,因此我认为即使在服务实现和静态变量中存在一些单例类(我们还没有使其成为线程安全)对象将被销毁,但我们观察到运行 SQL 分析器,旧值正在通过数据库。

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

请帮助我了解可能出了什么问题

4

3 回答 3

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

于 2014-11-15T15:23:08.363 回答
0

InstanceContextMode PerCall意味着每次调用都会实例化一个新的服务类。AppDomain 中的静态变量不会被重置。只要您的 AppPool 没有被回收,它们就会在服务调用之间停留。

从您的代码中删除所有静态变量,包括单例。无论如何,它们从来都不属于你的架构。

于 2014-11-15T11:17:43.603 回答
0

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

WCF 不会破坏您的任何对象,因为WCF 既不了解它们的含义,也不知道它们的存在

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

我对有状态服务器应用程序的通常建议:您在这里的做法很糟糕。您需要确保线程安全。如果工作进程关闭(部署、自动重启、服务器重启、应用程序错误导致进程崩溃、断电、硬件故障……),您的数据就会丢失。

于 2014-11-15T11:17:56.647 回答