WCF Best Practice #5: One-way is not always really one-way
In addition to the WCF Best Practices that are already around. WCF Best Practice #5: One-way is not always really one-way:
Be aware that the client.Close() can block until the service operation is done. Yes you read it right even when oneway closing a client can block until the service side is done. This is happening in quite some cases where bindings are configured to maintain sessions. This happens for example with Message security and or reliable session support.
There is a difference though in this behavior depending on how your contract is composed. This is between contracts with only oneway operations, which I'll call "Oneway contracts" and contracts that do have oneway operations combined with request-reply operations which I'll call "Mixed contracts".
Below is a table for the most common bindings. Check out if Proxy.Close() isn't blocking in the case where you want to do oneway operations:
| Binding |
SecurityMode |
reliableSession |
Close blocks (Mixed) |
Close blocks (Oneway only) |
|
basicHttpBinding (default)
|
None |
- |
No |
No |
| wsHttpBinding |
None |
False |
No |
No |
| wsHttpBinding |
None |
True |
Yes |
No |
|
wsHttpBinding (default)
|
Message |
False |
Yes |
Yes |
| wsHttpBinding |
Message |
True |
Yes |
No |
| netTcpBinding (default) |
Transport |
False |
Yes |
Yes |
| netTcpBinding |
None |
False |
Yes |
Yes |
| netTcpBinding |
None |
True |
Yes |
No |
| netTcpBinding |
Message |
False |
Yes |
Yes |
| netTcpBinding |
Message |
True |
Yes |
No |
Possible solutions if you don`t like the blocking proxy.Close():
- for wsHttpbinding: you could disable use of sessions in service contract via SessionMode.NotAllowed.
- for netTcpbinding: You can't disable sessions since they're used by the tcp transport. You could use streamed transfer mode. Be aware though that this is not working in combination with message security and or reliable sessions. basic, wsHttp or some queuing binding with binary encoding could be an alternative.
Also One-way != asynchronous. Lowy described this one here: http://msdn.microsoft.com/en-us/magazine/cc163537.aspx. The section I’m talking about:
"One-way calls do not equate to asynchronous calls. When one-way calls reach the service, they may not be dispatched all at once and may be queued up on the service side to be dispatched one at a time, all according to the service configured concurrency mode behavior and session mode. How many messages (whether one-way or request-reply) the service is willing to queue up is a product of the configured channel and the reliability mode. If the number of queued messages has exceeded the queue's capacity, then the client will block, even when issuing a one-way call. However, once the call is queued, the client is unblocked and can continue executing while the service processes the operation in the background. This usually gives the appearance of asynchronous calls. All the Windows Communication Foundation bindings support one-way operations."
So be aware of the situations in which a client still can block.