Problems with singleton pattern inside WCF service method
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.
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.
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.
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)
{
...
}
}
精彩评论