2

I am trying to understand how instances with WCF works. I have a WCF service which the InstanceContextMode set to PerCall (so for each call of every client a new instance will be created) and ConcurrencyMode set to Single (so the service instance is executing exactly one or no operation call at a time).

So with this I understand that when a client connects a new instance is created. But what happens when the client leaves the service. Does the instance die. The reason I ask is because I need to implement a ConcurrentQueue in the service. So a client will connect to the service and put loads of data to be processed and then leave the service. The workers will work of the queue. After the work is finished I need the instance to be destroyed.

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
Amitesh
  • 677
  • 1
  • 10
  • 24

2 Answers2

3

Basically, learning from the "WCF Master Class" tought by Juval Lowy, per-call activation is the preferred choice for services that need to scale, i.e. that need to handle lots of concurrent requests.

Why?

With the per-call, each incoming request (up to a configurable limit) gets its own, fresh, isolated instance of the service class to handle the request. Instantiating a service class (a plain old .NET class) is not a big overhead - and the WCF runtime can easily manage 10, 20, 50 concurrently running service instances (if your server hardware can handle it). Since each request gets its own service instance, that instance just handles one thread at a time - and it's totally easy to program and maintain, no fussy locks and stuff needed to make it thread-safe.

Using a singleton service (InstanceContextMode=Single) is either a terrible bottleneck (if you have ConcurrencyMode=Single - then each request is serialized, handled one after another), or if you want decent performance, you need ConcurrencyMode=Multiple, but that means you have one instance of your service class handling multiple concurrent threads - and in that case, you as a programmer of that service class must make 100% sure that all your code, all your access to variables etc. is 100% thread-safe - and that's quite a task indeed! Only very few programmers really master this black art.

In my opinion, the overhead of creating service class instances in the per-call scenario is nothing compared to the requirements of creating a fully thread-safe implementation for a multi-threaded singleton WCF service class.

So in your concrete example with a central queue, I would:

  • create a simple WCF per-call service that gets called from your clients, and that only puts the message into the queue (in an appropriate fashion, e.g. possibly transforming the incoming data or something). This is a quick task, no big deal, no heavy processing of any kind - and thus your service class will be very easy, very straightforward, no big overhead to create those class instances at all

  • create a worker service (a Windows NT service or something) that then reads the queue and does the processing - this is basically totally independent of any WCF code - this is just doing dequeuing and processing

So what I'm saying is : try to separate the service call (that delivers the data) from having to build up a queue and do large and processing-intensive computation - split up the responsibilities: the WCF service should only receive the data and put it into a queue or database and then be done with it - and a second, separate process should do the processing/heavy-lifting. That keeps your WCF service lean'n'mean

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
0

Yes, per call means, you will have a new insance of the service per each connection, once you setup the instance context mode to percall and ConcurrencyMode to single, it will be single threaded per call. when the client leaves, done with the job, your instance will dispose. In this case, you want to becareful not to create your concurrentqueue multiple times, as far as i can imagine, you will need a single concurrentqueue? is that correct?

I would recommend you to use IntanceContextMode=Single and ConcurrencyMode to Mutli threaded. This scales better.if you use this scheme, you will have a single concurrent queue, and you can store all your items within that queue.

One small note, ConcurrentQueue, has a bug, you should be aware of, check the bug database.

DarthVader
  • 52,984
  • 76
  • 209
  • 300
  • Thanks for the reply. Well I was not planning to use InstanceContextMode = Single with ConcurrencyContextMode = Multiple since there are other datacontracts in the service which are not thread safe. So I guess if I use just a normal queue where data will be pushed in and a worker thread will be started after the queue is load will work for me. I will just need to make sure that all the threads complete which will allow the instance to be disposed. – Amitesh Nov 23 '11 at 19:04
  • @marc_s what s the reason to disagree with single context mode and multithreaded? Per-call contexts are very expensive to create, dispose and maintain? especially having a centralized queue, how would integrate that into the per-call mode? – DarthVader Nov 23 '11 at 19:11
  • 1
    @marc_s http://msdn.microsoft.com/en-us/magazine/cc163590.aspx#S1 , please see the per-call method, each time you need to create a service, this is already very expensive itself. and this article states that this approach doesnt scale well. with a single context, you create one instance of the service and each call gets a new thread, it s very similar to httpd whereas per call is very similar to how perl-cgi used to work back in days. using a concurrent collection wouldnt make multi threading hard. – DarthVader Nov 23 '11 at 19:15
  • @marc_s I am not questioning your expertise, that s great. If you look at the last paragraph, you will see my point. I wasnt referring to the text you cited. and I had experience with this actually, that s why I m persistent with it. See the last paragraph "Per-call services clearly offer a trade-off in performance..... – DarthVader Nov 23 '11 at 19:21
  • @marc_s how you expect it to scale if you are spending lots of time creating/disposing instances? do you believe it yourself? – DarthVader Nov 23 '11 at 19:28
  • Per-Call is plenty fast enough when self-hosting, but if you are hosting in IIS/using WAS then (I believe) ServiceHost needs to be constructed on each call *before* the Service is constructed. That's where the overhead is. Creating an instance of a service class is barely any overhead at all. – Kirk Broadhurst Nov 23 '11 at 23:45
  • self hosting via Program or Service is tough, you need to deal with all possible errors, downtime, logging etc. IIS hosting/WAS deals with these and has benefits. – DarthVader Nov 23 '11 at 23:51