3

I am currently looking at some code which basically reads data line-by-line from a file and calls an appropriate method on a WCF client for each line. My problem with the code is that a new client is created for each operation ie:

function CallSomeOp(line)
 {
   using (var client = new Client()
   {
       client.SomeOp(line);
   }
 }

This seems to make the client close the connection and reopen a new one for each line in the file which seems like a big overhead. What I would like to do is move the creation of the client outside the function and into initialization, so that multiple operations are called on one client, ie:

 using (var client = new Client())
 {
     for(var line in lines)
     {
        CallSomeOp(line, client);
     }
 }

But I'm not sure if this is OK or not. Is there some problem with calling multiple operations on a client, ie will I eventually run out of memory or something?

Wouter de Kort
  • 39,090
  • 12
  • 84
  • 103
avid
  • 579
  • 5
  • 18

2 Answers2

2

An operation is typically stateless, so that's expected behaviour. You can change the InstanceContextMode though. This determines if a new instance is created with each call or that there is a single instance. The question is, should you? Like I said, a single call is typically stateless. Having just a single instance doesn't scale very well either. I'd suggest to keep InstanceContextMode to be PerCall, that way, for every call the webserver creates a single instance, I wouldn't worry too much about overhead. If overhead really does become a problem, maybe a service isn't what you need.

Then there's the ConcurrencyMode which allows you to specify multiple threads to be created.

As far as the client is concerned, you don't need to re-create it everytime you want to call an operation. Alternatively, you could also look at the ChannelFactory if both client and server have knowledge of the contract. This answer provides some detail.

Community
  • 1
  • 1
diggingforfire
  • 3,359
  • 1
  • 23
  • 33
  • Thanks for the answer, I did an experiment with a profiler and using a single instance reduced the running time from 58 seconds to around 25. I don't know that much about WCF but this seems like a quick win. – avid Feb 06 '12 at 11:56
  • Can you post some code of your service? What does it do? Be mindful of the fact that a single instance could lead to scaling problems with many calls. – diggingforfire Feb 06 '12 at 11:57
  • I cannot post the code of the service and I'm not entirely sure what it does! It should just take some data and put it somewhere. The applicant using the client is single threaded. – avid Feb 06 '12 at 12:05
2

It's definitely a good idea to reuse a WCF client across multiple calls, since there is indeed a cost in creating new instances of it, even if that's been improved in later versions.

The most important thing to be aware of when reusing a WCF client, though, is that if a service operation fails, the whole client will be put in a faulted state and can no longer be used.

You will have to take this into consideration in your client code. Depending on your requirements, one way to handle this situation could be to recreate the client proxy in case of failure and continue processing the input, like shown in this example:

var client = new ServiceClient();

foreach (var line in lines)
{
    try
    {
        client.DoSomething(line);
    }
    catch
    {
        client.Abort();
        client = new ServiceClient()
    }
}

Note that you may also want to keep track of how many times the service call fails and with what type of exception, since in some situations it would make more sense to completely abort the operation instead of keep trying, e.g. when the remote service is not reachable.

Enrico Campidoglio
  • 56,676
  • 12
  • 126
  • 154