Geeks With Blogs
Marcin Celej blog

This is one of the Windows Communication Foundation mysteries. I still don't know why the code below does not (really) work:

for (int i = 0; i < 100; i++)
{
    IMyService proxy = new ChannelFactory("MyService").CreateChannel();
    proxy.DoSomething();

    // Without this line the proxy invocation fails on the 10th DoSomething() method call
    // ((IChannel)proxy).Close();
}

 

When the proxy.Close() is commented, in the code above, the WCF throws the TimeoutException on the 11th proxy invocation (the variable i == 10). So the first 10 requests works properly and the 11th one throws the exception:

A first chance exception of type 'System.TimeoutException' occurred in mscorlib.dll

Additional information: The open operation did not complete within the allotted timeout of 00:01:00. The time allotted to this operation may have been a portion of a longer timeout.

My first thought when I figured out that it is caused by lack of the Close() method call was: Why the hell I have to close the proxy?

I tried to find out why, but the only reason I see is this one: WCF session is managed by client proxy lifetime so when you close the proxy it sends such information to serever so the remote service could be released. But my service is not session-bound so I think I don't need to close it.

I tried one more thing: I added GC.Collect() instead of the proxy.Close() and everything worked fine - destroying proxy with GC closes it.

This behavior looks weirdy to me, as it can occur not on the 11th proxy invocation but during the 13, 25 or any other if the Garbage Collector is involved. This can cause mistakes and application strange behavior.

Anyway: why do we really need to close the service proxy? I am still looking for the answer - I'll post it when I find it.

Posted on Tuesday, May 1, 2007 2:33 PM | Back to top


Comments on this post: WCF - why do I have to Close a service proxy?

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
What binding are you using? Almost all of the standard bindings (including net.tcp + wsHttp) are sessionful in some way or another.

You're hitting the MaxConcurrentSessions throttle on the server (which defaults to 10). Since you're not closing the proxies when you're done with them, the first 10 calls will succeed because they can establish new sessions up to the server's limit. The 11th call will block until one of the other sessions get torn down -- either by explicitly calling proxy.Close() on the client, or by implicitly calling Close() during finalization.

Anyway, the answer to why you need to close the proxy is because closing the proxy tears down all the associated channel state and frees up space on the server to process new requests.

Hope that helps
-steve
Left by Steve Maine on May 06, 2007 6:27 PM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
I bet if you declare your proxy in a using block you won't have to think about it.
Left by Matt Youell on May 22, 2007 5:40 AM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
Dude! I'm facing the exact same problem and I can't figure out WHY I has to implcitly close the Channel. It makes no sense...

And I don't know, Steve's answer doen't convince me :s
Left by Seba Gomez on Sep 11, 2007 6:30 AM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
I got communication exception errors (only visible at service log though) when calling WCF function without closing its proxy afterward. You may see this problem I posted at :
http://forums.microsoft.com/msdn/ShowPost.aspx?postid=2127853&amp;isthread=false&amp;siteid=1&amp;authhash=37f516fa32dcced428dc90979fea5d51eb2f1434&amp;ticks=633251350662054330

However, unlike the scenario described here that the WCF function doSomething() is called repeatively in a loop, my client side program invokes a WCF function only one time in the code block. I assmue the proxy becomes out-of-scope but GC does not release it soon and the associated channel is left open.
Left by Rick Lee on Sep 11, 2007 2:37 PM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
Hey have u found solution of the same problem because i am facing the same one in my solution also and using wsHttpBindng..hoping for ur answer.
Thnx
Left by kiran on Dec 25, 2007 10:40 PM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
Hi,

I'm not sure if this is still an issue, but WCF has some default service throttling settings, which are configurable. The default setting for maxConcurrentSessions is 10 which is why you're only hitting a problem at 10 connections. To modify the defaults, add a behaviour as follows to the <system.serviceModel><behaviours> section in the config file for the service:
<behavior name="ThrottledBehavior">
<serviceThrottling
maxConcurrentCalls = "64"
maxConcurrentSessions = "50"
maxConcurrentInstances = "1"
/>
</behavior>
In the example above I have throttled concurrent sessions to 50, so I get to 50 before getting timeouts when attempting to open connections.

Once you've defined your behaviour, apply the behaviour configuration to your service by adding the "behaviourConfiguration" attribute and setting the value equals to the behaviour name defined in your behaviour configuration (in our example it would be "ThrottledBehavior").

e.g.

<service name="MyService" behaviorConfiguration="ThrottledBehavior">

If you have already applied a behaviorConfiguration attribute, just add the <serviceThrottling> section of the example above to the existing behaviour configuration.

You may also have to set MaxConnection settings on your bindings configurations.
Left by Amy on Jan 15, 2008 7:37 PM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
Thank you Amy for your hint. I already know it but thank you for your help.

Marcin
Left by Marcin Celej on Jan 16, 2008 10:45 AM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
I was having this problem too. Following Matt's comment above, I applied a using block to the service proxy object, and it solved the problem nicely.
Left by Jacob on Feb 16, 2008 11:50 AM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
http://www.cazed.com


The only proxy that seems to work...
Left by Ted on Aug 10, 2008 8:03 PM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
This post was extremely helpful. I tried both Steve's and Matt's suggestions and both worked great. I ended up going with the using statement solution.
Left by Aaron on Sep 03, 2009 1:47 AM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
Great - this list of postings have saved my day. I was having the same problem with the limit of the 10 concurrent connections and even though I did null my connection object this would not be closed before the GC would kick in much later.
I have just tried the using statement solution and it works great.
Thanks for sharing.
Peter
Left by Peter on Sep 08, 2009 8:49 PM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
Hi again,
I have just read some more about this problem and it seems that there may be a catch with the using statement.

Have a look here:
http://www.codeguru.com/csharp/.net/net_wcf/article.php/c15941/

I have tested this fix and it works in my program.

Peter
Left by Peter on Sep 08, 2009 9:22 PM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
Peter, Many thanks for the link. The tip is great. If I were you I would create a class, let's call it a ProxyDisposer that implements the IDisposable interface. The class could be used this way:

using(var client = new ProxyDisposer (new StockService.StockServiceClient(...)))
{
client.InnerProxy.GetStockIdByName("MSFT");
}

So the ProxyDisposer takes as an argument a real proxy to the service and it exposes it via InnerProxy property. In the Dispose() method the ProxyDisposer should do what is mentioned in the article you provided.

That's nice piece of utility class.

Marcin Celej
MVP Visual C#
Left by Marcin Celej on Sep 08, 2009 9:42 PM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
if u left the proxy instantiation outside the loop u wont create a new session for each call but use the same proxy for all calls,,,then you wont get the max session issue
Left by ChristianLarsen on Oct 05, 2009 9:49 PM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
See http://timrayburn.net/blog/idisposable-wcf-and-hole-in-the-middle/ for more details.
Do not use "using" construction with client proxy. It will cause the several issues!
Left by BorodaAlex on Apr 01, 2010 12:09 AM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
hi..
can some1 plzzzzz help me out this weird problem ..i tried all options given above but in vain....
Left by Mumtaz on Sep 07, 2010 10:39 PM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
Hi!

I have a WCF service with wsHttpBinding. When I add a web reference in my web application VS 2008 generates the proxy...then when I call the service proxy I can´t get the Close() method neither use "using" block because the proxy doesn't implements IDisposable. Can anybody helpe me please!!! I'm pretty new with WCF. Thank you
Left by Juliana on Sep 08, 2010 9:23 AM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
I think I might have some under-the-covers insight. I know this post is old but it is also a top search result so I had to share.

I don't know if the same reasoning applies with a named pipes binding but other bindings use TCP socket connections (since HTTP is over TCP). Socket connections will remain in a CLOSE_WAIT status until directed to close. The timeout for a CLOSE_WAIT is quite long...VERY LONG. Run NETSTAT in a command prompt to have a peak at your current connections. (Don't worry about TIME_WAIT that is like good cholesterol)

As long as that socket connection is open in a CLOSE_WAIT status , you are chewing up one of your available MaxConcurrentSessions (default 10), MaxConcurrentInstances (default 26), and MaxConcurrentCalls (default 16). Notice the defaults for those are unreasonably low for just about 99% of systems. Never accept those default values. Think about the throughput your service will accept in a full load scenario and set accordingly. At my organization, knowing my systems, I can't imagine supporting less than 100 for all three settings. If you don't close your proxies then you are maintaining 10 open sessions to your service until garbage collection gets your proxies. Yes, 10! Once you hit your service throttling thresholds, all additional requests queue up on the server. This means your 11th call is sitting in a queue waiting for the garbage collector to kill naughty clients. Since GC doesn't come to dinner often: your client timeout lapses; you recieve the error you mentioned; and Bob's your uncle.

I don't think ASMX has these throttling settings on by default (or avilable at all?) so you wouldn't likely see the clients timeout like this but you would see chaos in NETSTAT if you forgot to call Dispose on your proxy. I've had busy services chew up the entire dynamic port range because of undisposed (read: unclosed) ASMX proxy objects. It was a deluge of CLOSE_WAITS. That wasn't exacly a DoS attack however I'm thankful WCF at least lets me control when to start queuing client requests, potentially timing out clients, before my important back end resources start toppling over if there were a DoS attack.

In short:
1) Set your throttling (ALWAYS)
2) Close your proxies (Close alone doesn't cut it)
3) Close your proxies (Displose alone doesn't cut it)
4) Close your proxies (Stay away from Using blocks)
5) Close your proxies (Call Abort, not Close, if proxy is in a Faulted state)
6) Close your proxies (Don't reuse a Faulted proxy)
Left by Matt Poland on Feb 14, 2011 10:41 AM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
thx dude, my app was freezing up after... about 10 invocations :D
Left by Gelu on May 06, 2011 12:55 AM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
Did you find the awnser to your question?

I was wondering the same thing
Left by Ryno on Oct 04, 2011 2:32 AM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
Hi there,

After a lot of time, with Close / Dispose - http://ardalis.com/idisposable-and-wcf
The only way I got this thing to work was with the: GC.Collect()

Not a very pretty solution but it works ...
Left by Tiago on Sep 04, 2012 10:11 PM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
I know this is late in the game, but this may help others. I had the same problem. a using statement would not work for me as the channel does not implement IDisposable (as stated by another above). I closed the connection using the following logic... Closing the channel in the finally does work.

ICustomSearchServices iCustomServices = new ChannelFactory<ICustomSearchServices>("WSHttpBinding_ICustomSearchServices", endpointAddress).CreateChannel();

AsyncCallback aSyncCallBack =
delegate(IAsyncResult result)
{
try
{
recordCount = iCustomServices.EndYourMethod(result);

_Owner.BeginInvoke((Action)delegate { StatusMessage(string.Format("{0} record(s) updated.", documentCount)); });
}
catch (Exception ex)
{
_Owner.BeginInvoke((Action)delegate { StatusMessage(string.Format("An error occurred while syncronizing records.", documentCount)); });
}
finally
{
((System.ServiceModel.Channels.IChannel)iCustomServices).Close();
}
};

try
{
iCustomServices.BeginYourMethod(methodParm, methodParm, aSyncCallBack, iCustomServices);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Left by Dave on Sep 18, 2012 5:32 AM

# re: WCF - why do I have to Close a service proxy?
Requesting Gravatar...
The problem is that you create 10 different channels without closing any of them. Just because you no longer have a refernce to one it does not mean it is closed. Calling the garbage collector spots that there are no references to one and disposes of it.

Try putting the create channel line above the for loop. That way you only create one channel and make a number of calls on that one channel. Don't forget to close the channel after the loop has finished.
Left by John Thompson on Nov 06, 2012 1:33 AM

Your comment:
 (will show your gravatar)
 


Copyright © Marcin Celej | Powered by: GeeksWithBlogs.net | Join free