WCF服务方法中单例模式的问题

时间:2011-08-01 12:15:52

标签: c# .net wcf web-services singleton

我将继续前言,并说:我对WCF有点新鲜。

我正在研究一个负责执行大量业务逻辑的服务器端例程。它可以通过WCF从客户端访问。

我的主要WCF方法调用其他几个私有方法。我决定使用名为DataProvider的类的单例实例来包含所有这些“查找数据”,而不是传递我对每个私有方法的业务逻辑所需的所有“查找数据”。

在例程结束时,我“释放”DataProvider的查找数据,以便下次执行例程时,将使用最新的查找数据。

所以,这是一个简化的例子:

 public void Generate()
 {
      try
      {
           //populate singleton DataProvider with it's lookup data...
           DataProvider.Instance.LoadLookupData();

           //do business logic...
      }
      finally
      {
           //release provider's lookup data...
           DataProvider.Release();
      }
 }

这很有效,直到我有两个不同的客户端在同一时间(或接近)执行该方法。出现问题的原因是它们共享相同的单例实例,而先完成的任务将在另一个完成之前释放DataProvider。

因此...

我有什么选择?

我想避免传递所有查找数据,因此单例模式(或某些衍生物)似乎是一个不错的选择。我还需要能够支持同时调用该方法的多个客户端。

我认为WCF服务配置为“Per-Call”。我不确定是否有办法配置WCF服务,以便在服务调用之间不共享静态内存。

任何帮助都将不胜感激。

3 个答案:

答案 0 :(得分:8)

默认情况下,WCF使用" Per-Call",这意味着为每个客户端的呼叫创建了WCF服务的新实例。既然你已经实现了单例,即使创建了WCF的新实例,它仍然会调用你的单例。

如果您想创建为每个调用创建的查找(就像您现在所做的那样),则不应将其作为单例执行。这样调用方法的每个客户端都会有新的查找实例,我认为这是你的意图。

但是,如果您的查找速度没有那么快,我建议在所有调用之间共享,这样可以提高WCF服务的性能。您需要将WCF服务声明为

InstanceContextMode = InstanceContextMode.Single
ConcurrencyMode = ConcurrencyMode.Multiple  

这样做的目的是由WCF自动为您创建单身人士,因此您不必自己动手,其次它将支持> 1个并发用户(ConcurrencyMode.Multiple)。

现在,如果您的查找正在发生变化,并且需要在一段时间后重新加载,我仍然建议您使用

InstanceContextMode = InstanceContextMode.Single 
ConcurrencyMode = ConcurrencyMode.Multiple

但在你的代码内部缓存它然后在特定时间或相对时间(1小时)使你的缓存失效。

以下是一些可能对您有所帮助的链接: 3 ways to do WCF instance management (Per call, Per session and Single)

希望这会有所帮助。

答案 1 :(得分:4)

无论WCF InstanceContextMode setting.如何,WCF服务中的静态变量总是在实例之间共享。看起来您最好使用缓存模式来查找数据。 answers to this caching question提供了一些替代方案来推销自己,尽管它们有点过时了。

此外,如果您决定使整个服务实例成为单例(InstanceContextMode = Single)是最简单的解决方案,请注意您通常会破坏服务可伸缩性,除非您还使代码具有多线程(ConcurrencyMode=Multiple)。如果您可以在睡眠中删除线程安全的代码,那么单身人士服务可能适合您。

答案 2 :(得分:1)

最简单的是使用同步机制 - 你看过锁(...) - 这将作为一个看门人很像一个关键部分(如果你遇到过windows编程中的那些)

在类中定义一个静态对象

即。

static object lockObject = new object();

并在Generate method

中使用它

void Generate()
{
    lock(lockObject)
    {
    ...
    }
}