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

发布于 2024-11-27 02:13:50 字数 893 浏览 0 评论 0原文

我将在前言中说:我对 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 服务被配置为“每次调用”。我不确定是否有办法配置 WCF 服务,以便在服务调用之间不共享静态内存。

任何帮助将不胜感激。

I will go ahead and preface this by saying: I am somewhat new to WCF.

I'm working on a server-side routine that's responsible for doing a great deal of business logic. It's accessible from a client via WCF.

My main WCF method calls off to several other private methods. Instead of passing around all of the "lookup data" I need for the business logic to each private method, I decided to use a singleton instance of a class named DataProvider that contains all of this "lookup data".

At the end of the routine, I "release" the DataProvider's lookup data so the next time the routine is executed, the latest lookup data will be used.

So, here's a simplified example:

 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();
      }
 }

This works great until I have two different clients that execute the method at (or near) the same time. Problems occur because they share the same singleton instance and the task who finishes first will release the DataProvider before the other completes.

So...

What are my options here?

I'd like to avoid passing around all of the lookup data so the singleton pattern (or some derivative) seems like a good choice. I also need to be able to support multiple clients calling the method at the same time.

I believe the WCF service is configured as "Per-Call". I'm not sure if there's a way to configure a WCF service so that the static memory is not shared between service invocations.

Any help would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

执妄 2024-12-04 02:13:50

默认情况下,WCF 使用“Per-Call”,这意味着为每个客户端的调用创建 WCF 服务的新实例。现在,由于您实现了单例,即使创建了 WCF 的新实例,它仍然会调用您的单例。

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

但是,如果您的查找变化不那么快,我建议在所有调用之间共享它,这将提高 WCF 服务的性能。您需要将您的 WCF 服务声明为

InstanceContextMode = InstanceContextMode.Single
ConcurrencyMode = ConcurrencyMode.Multiple  

“它的作用是通过 WCF 自动为您创建单例”,因此您不必自己执行此操作,其次它会支持 > 1 个并发用户 (ConcurrencyMode.Multiple)。

现在,如果您的查找正在更改并且需要在一段时间后重新加载,我仍然建议

InstanceContextMode = InstanceContextMode.Single 
ConcurrencyMode = ConcurrencyMode.Multiple

在代码缓存中使用 but ,然后在特定时间或相对时间(1 小时)使缓存过期。

以下是一些可能对您有帮助的链接:
3 种进行 WCF 实例管理的方法(按调用、按会话和单个)

希望这会有所帮助。

By default WCF is using "Per-Call", which means new instance of the WCF service is created for each client's call. Now since you implemented singleton even though new instance of the WCF is created it still calls your singleton.

If you would like to create lookup that is created for each call (like you have now) you should not do it as singleton. This way each client that calls your method will have new instance of the lookup, I think that was your intention.

However if you have lookup that is not changing that fast, I would recommend to share it between all calls, this will improve performance of your WCF service. You will need to declare your WCF service as

InstanceContextMode = InstanceContextMode.Single
ConcurrencyMode = ConcurrencyMode.Multiple  

What this does is creating Singleton automatically for you by WCF, so you don't have to do it yourself, second it will support > 1 concurrent user (ConcurrencyMode.Multiple).

Now if you have your lookup that is changing and it needs to be reloaded after some period of time, I still would recommend using

InstanceContextMode = InstanceContextMode.Single 
ConcurrencyMode = ConcurrencyMode.Multiple

but inside in your code cache it and then expire your cache at specific time or relative time (1 hours).

Here are some links that might help you:
3 ways to do WCF instance management (Per call, Per session and Single)

Hope this will help.

紫轩蝶泪 2024-12-04 02:13:50

WCF 服务中的静态变量始终在实例之间共享,无论 WCF InstanceContextMode 设置。 看来您最好使用缓存模式来查找数据。 此缓存问题的答案提供了一些替代方案来替代您自己的方案,尽管它们有点过时。

另外,如果您决定将整个服务实例设置为单例 (InstanceContextMode=Single) 是最简单的解决方案,请注意,您通常会破坏服务的可扩展性,除非您还使代码多线程 (ConcurrencyMode=Multiple)。如果您可以在睡觉时敲出线程安全代码,那么单例服务可能适合您。

The static variables in a WCF service are always shared between instances regardless of the WCF InstanceContextMode setting. It seems you would be better off using a caching pattern for your look up data. The answers to this caching question provide some alternatives to rolling your own although they are a bit dated.

Also, if you decide that making the whole service instance a singleton (InstanceContextMode=Single) is the easiest solution be aware that you'll generally kill service scalability unless you also make your code multi-threaded (ConcurrencyMode=Multiple). If you can knock out thread-safe code in your sleep then a singleton service might be for you.

半岛未凉 2024-12-04 02:13:50

最简单的是使用同步机制 - 你看过 lock(...) - 这将充当一个看门人,很像关键部分(如果你在 Windows 编程中遇到过那些)

在你的类中定义一个静态对象

,即

static object lockObject = new object();

并在生成方法中使用它,

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

simplest is to use a synchronization mechanism - have you looked at lock(...) - this will act as a gatekeeper a lot like a critical section (if you have come across those in windows programming)

define a static object in your class

i.e.

static object lockObject = new object();

and use it in Generate method

i.e.

void Generate()
{
    lock(lockObject)
    {
    ...
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文