Problems with singleton pattern inside WCF service method

I will continue and precede this by saying: I am somewhat new to WCF.

I am working on a server-side procedure that is responsible for executing large business logic. It is available through the client through WCF.

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

At the end of the procedure, I “free” the DataProvider search data, so the next time the search data is used the next time the subroutine is launched.

So here is a simplified example:

public void Generate() { try { //populate singleton DataProvider with it lookup data... DataProvider.Instance.LoadLookupData(); //do business logic... } finally { //release provider lookup data... DataProvider.Release(); } } 

This works fine until I have two different clients that execute the method in (or near) at the same time. Problems arise because they use the same singleton instance, and a task ending first will release the DataProvider before the other completes.

So...

What are my options here?

I would like to get around all the search data, so a singlet template (or some kind of derivative) seems like a good choice. I should also be able to support multiple clients calling this method at the same time.

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

Any help would be appreciated.

+8
c # singleton web-services wcf
source share
3 answers

By default, WCF uses "Per-Call", which means that a new instance of the WCF service is created for each client call. Now that you have implemented singleton, even if you created a new instance of WCF, it still calls your singleton.

If you want to create a search created for each call (for example, you have one), you should not do this as a singleton. This way, every client that calls your method will have a new search instance, I think that was your intention.

However, if you have a search that doesn't change so fast, I would recommend sharing it between all the calls, which will improve the performance of your WCF service. You will need to declare your WCF service as

 InstanceContextMode = InstanceContextMode.Single ConcurrencyMode = ConcurrencyMode.Multiple 

This means that it automatically creates Singleton automatically for WCF, so you do not need to do this yourself, and secondly, it will support> 1 concurrent user (ConcurrencyMode.Multiple).

Now, if you have your search that is changing and needs to be reloaded after a certain period of time, I would recommend using

 InstanceContextMode = InstanceContextMode.Single ConcurrencyMode = ConcurrencyMode.Multiple 

but inside in your code cache, and then your cache expires at a specific time or relative time (1 hour).

Here are some links that may help you: 3 ways to manage a WCF instance (per call, per session, and single)

Hope this helps.

+8
source share

Static variables in the WCF service are always shared between instances regardless of the WCF InstanceContextMode parameter. It seems you would be better off using a caching pattern to find data. The answers to this caching question provide some alternatives to switching to your own, although they are a bit outdated.

In addition, if you decide that creating an entire instance of a singleton service (InstanceContextMode = Single) is the easiest solution, you should be aware that you tend to reduce the scalability of services, unless your code is multithreaded (ConcurrencyMode = Multiple) . If you can get a thread safe code while you sleep, you might need a singleton service.

+4
source share

The simplest is to use the synchronization mechanism - you looked at the lock (...) - it will act as a gatekeeper, very similar to a critical section (if you came across them in window programming)

define a static object in your class

i.e.

 static object lockObject = new object(); 

and use it in the Generate method

i.e.

 void Generate() { lock(lockObject) { ... } } 
+1
source share

All Articles