A Bit More on Call Context Initializers
In the last article on call context initializers, the sample program included three bindings to try out. All the program did was trace the thread ID being used for a particular call when the service method was invoked or when the call context initializer was either creating or destroying the call context. The three bindings were:
1.
TCP
2.
One-way over TCP
3.
Secure Conversation over Composite Duplex over One-way over TCP
Now, each of these bindings was created by extending the previous binding with additional binding elements. There weren't any setting changes or alterations to earlier binding elements in the channel stack. The service was using an instance per service call.
If you ran the sample program with the first or third bindings, you'd get something like this:
Invoke: Client11
Invoke: Client12
Invoke: Client13
Invoke: Client14
Invoke: Client16
Invoke: Client17
Invoke: Client18
Invoke: Client19
Invoke: Client20
Invoke: Client21
BeforeInvoke: Server22
Invoke: Client11 Server22
AfterInvoke: Server22
BeforeInvoke: Server22
Invoke: Client12 Server22
AfterInvoke: Server22
BeforeInvoke: Server22
Invoke: Client13 Server22
AfterInvoke: Server22
BeforeInvoke: Server22
Invoke: Client14 Server22
AfterInvoke: Server22
BeforeInvoke: Server22
Invoke: Client16 Server22
AfterInvoke: Server22
BeforeInvoke: Server22
Invoke: Client17 Server22
AfterInvoke: Server22
BeforeInvoke: Server22
Invoke: Client18 Server22
AfterInvoke: Server22
BeforeInvoke: Server22
Invoke: Client19 Server22
AfterInvoke: Server22
BeforeInvoke: Server22
Invoke: Client20 Server22
AfterInvoke: Server22
BeforeInvoke: Server22
Invoke: Client21 Server22
AfterInvoke: Server22
Notice how all of the client calls are serialized and run on a single thread. If you ran the sample program with the second binding, you'd get a different looking result.
Invoke: Client11
Invoke: Client12
Invoke: Client13
Invoke: Client15
Invoke: Client16
Invoke: Client17
Invoke: Client18
Invoke: Client19
Invoke: Client20
Invoke: Client21
BeforeInvoke: Server22
Invoke: Client11 Server22
AfterInvoke: Server22
BeforeInvoke: Server22
Invoke: Client12 Server22
AfterInvoke: Server22
BeforeInvoke: Server22
Invoke: Client13 Server22
AfterInvoke: Server22
BeforeInvoke: Server22
Invoke: Client15 Server22
BeforeInvoke: Server23
Invoke: Client16 Server23
AfterInvoke: Server23
AfterInvoke: Server22
BeforeInvoke: Server22
Invoke: Client17 Server22
BeforeInvoke: Server23
Invoke: Client18 Server23
BeforeInvoke: Server24
Invoke: Client19 Server24
AfterInvoke: Server22
BeforeInvoke: Server22
Invoke: Client20 Server22
AfterInvoke: Server23
BeforeInvoke: Server23
Invoke: Client21 Server23
AfterInvoke: Server22
AfterInvoke: Server24
AfterInvoke: Server23
It's only when you switch bindings that you actually get any concurrency. With the second binding, we finally see multiple threads and calls happening out of order. The key difference is that although there were multiple threads, all of the client calls for the sample program are being made on the same channel object. That means for the first and third binding that all of the calls are taking place on a single session channel. In the case of the first binding, the session comes from the TCP connection. In the case of the third binding, the session comes from using message security. In between these two cases, the one-way channel is discarding the TCP session because it consumes a duplex session channel and produces an input or output channel.
Next time: TryReceive and Exceptions
Comments
- Anonymous
April 27, 2007
Why are all of the TCP sockets for my HTTP application owned by PID 4? The "-o" option of netstat tells