Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>I am not sure but here is how I understand this for a Duplex mode communication.</strong></p> <p>I had a look at the InstanceContext class defined in the System.ServiceModel assembly using dotPeek decompiler.</p> <p>Internally there is a call</p> <pre><code>this.channels = new ServiceChannelManager(this); </code></pre> <p>That means, it is creating channel using a ServiceChannelManager passing in the instance of the same InstanceContext. This way it keeping a track of the Channel with the instance of InstanceContext.</p> <p>Then is binds Incoming channel (Service to Client) requests in method that is implemented as :</p> <pre><code>internal void BindIncomingChannel(ServiceChannel channel) { this.ThrowIfDisposed(); channel.InstanceContext = this; IChannel channel1 = (IChannel) channel.Proxy; this.channels.AddIncomingChannel(channel1); if (channel1 == null) return; switch (channel.State) { case CommunicationState.Closing: case CommunicationState.Closed: case CommunicationState.Faulted: this.channels.RemoveChannel(channel1); break; } } </code></pre> <p>So to answer your queries :</p> <p>a. Yes, it internally maintains the Service and InstanceContext (which creates a channel) relations for calls between Client and Service.</p> <p>b. Yes, the channel needs to stay opened untill the Service replies back to the context, in which the InstanceContext will take care of closing the channel.</p> <p>c. Each client has a unique Session Id, but the InstanceContext type at the Service depends on the InstanceContextMode used at the Service on the implementation of the Contract.</p> <p>d. It uses the same channel. InstanceContext maintains a count of IncomingChannel and Outgoing channel. Incoming channel are the one that are Service to Client directed and Outgoing are Client to Service directed. You can see this count using debugger in VS.</p> <p>For the sake of further clarification, as far as the other behavior for a Duplex service is concerned, here is how we can look at the behavior of InstanceContext and how channel instance is created :</p> <p>I created a Duplex service demo :</p> <pre><code>[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IServiceDuplexCallback))] public interface IServiceClass { [OperationContract(IsOneWay = true)] void Add(int num1); } </code></pre> <p>This contract is implemented as :</p> <pre><code>[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] public class ServiceClass : IServiceClass { int result = 0; public void Add(int num1) { result += num1; callBack.Calculate(result); } IServiceDuplexCallback callBack { get { return OperationContext.Current.GetCallbackChannel&lt;IServiceDuplexCallback&gt;(); } } } </code></pre> <p>In this implementation notice the first line where InstanceContextMode is set to PerCall. <strong>The default is PerSession.</strong></p> <p>This enumeration has three options:</p> <ol> <li><p>PerCall - New instance of InstanceContext used for every call independent of Session</p></li> <li><p>PerSession - New instance used for every session</p></li> <li><p>Single - A single instance of InstanceContext used for all the clients.</p></li> </ol> <p>I created a client which use NetTcpBinding to connect with Service :</p> <pre><code>InstanceContext ic = new InstanceContext(new TCPCallbackHandler(ref textBox1)); TCP.ServiceClassClient client = new TCP.ServiceClassClient(ic); // First call to Add method of the Contract client.Add(val1); // Second call to Add method of the Contract client.Add(val2); </code></pre> <p>TCPCallbackHandler is the class in the Client that implements the Callback contract as:</p> <pre><code>public class TCPCallbackHandler : TCP.IServiceClassCallback { TextBox t; public TCPCallbackHandler(ref TextBox t1) { t = t1; } public void Calculate(int result) { t.Text += OperationContext.Current.SessionId + " " + result.ToString(); } } </code></pre> <p>To see the behavior of the InstanceContext, I started the service and then started two clients with each enumeration operation as discussed above. Here are the results :</p> <p><strong>1 - PerCall</strong></p> <p>Client 1 : urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 <strong>5</strong> - urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 <strong>5</strong></p> <p>Client 2 : urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f01 <strong>5</strong> - urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f01 <strong>5</strong></p> <p>Here - <strong>urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 is SessionId</strong></p> <p>Since for each client Add is called twice in the Client, and in PerCall -> new instance of InstanceContext is created every call, we create a new instance of ServiceClass for both the calls of every client. Point to note here is that new instance is created even for the same session</p> <p>// First call to Add method of the Contract</p> <p>client.Add(val1); <strong>-> New Instance of ServiceClass created and value will be incremented to 5</strong></p> <p>// Second call to Add method of the Contract</p> <p>client.Add(val2); <strong>-> New Instance of ServiceClass created and value will be incremented to 5</strong></p> <p><strong>2 - PerSession</strong></p> <p>Client 1 : urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 <strong>5</strong> - urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 <strong>10</strong></p> <p>Client 2 : urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f01 <strong>5</strong> - urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f01 <strong>10</strong></p> <p><strong>Here the instance of ServiceClass is separate for both the client as they have different sessions running. So the increment in the calls is 0 -> 5 -> 10 (for both client separately)</strong></p> <p><strong>3 - Single</strong></p> <p>Client 1 : urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 <strong>5</strong> - urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 <strong>10</strong></p> <p>Client 2 : urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f01 <strong>15</strong> - urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f01 <strong>20</strong></p> <p>Here the same instance of ServiceClass is shared by all clients so we have 0 -> 5 -> 10 in first client. The second client will increment in the same instance, so we get 10 -> 15 -> 20.</p> <p>This will behave differently as per the call and may give result like when invoked at the same time from the clients.</p> <p>Client 1 : urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 <strong>5</strong> - urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 <strong>15</strong></p> <p>Client 2 : urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f01 <strong>10</strong> - urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f01 <strong>20</strong></p> <p><strong>Hope this helps!</strong></p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload