Я не уверен, но вот как я понимаю это для связи в дуплексном режиме.
Я посмотрел на класс InstanceContext, определенный в сборке System.ServiceModel, используя декомпилятор dotPeek.
Внутренний вызов
this.channels = new ServiceChannelManager(this);
Это означает, что он создает канал с использованием ServiceChannelManager, передавая экземпляр того же InstanceContext.Таким образом, он отслеживает канал с экземпляром InstanceContext.
Затем связывает входящие запросы канала (службы к клиенту) в методе, который реализован как:
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;
}
}
ответьте на ваши вопросы:
a.Да, он поддерживает отношения Service и InstanceContext (который создает канал) для вызовов между Клиентом и Сервисом.
b.Да, канал должен оставаться открытым, пока Сервис не ответит обратно в контекст, в котором InstanceContext позаботится о закрытии канала.
c.Каждый клиент имеет уникальный идентификатор сеанса, но тип InstanceContext в Сервисе зависит от InstanceContextMode, используемого в Сервисе при реализации Договора.
d.Он использует тот же канал.InstanceContext поддерживает количество входящего канала и исходящего канала.Входящий канал - это канал, ориентированный на обслуживание к клиенту, а исходящий канал направлен на обслуживание от клиента.Вы можете увидеть это количество, используя отладчик в VS.
Ради дальнейшего пояснения, что касается другого поведения для дуплексной службы, вот как мы можем посмотреть на поведение InstanceContext и как каналэкземпляр создан:
Я создал демонстрационную версию службы дуплексной связи:
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IServiceDuplexCallback))]
public interface IServiceClass
{
[OperationContract(IsOneWay = true)]
void Add(int num1);
}
Этот контракт реализован как:
[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<IServiceDuplexCallback>();
}
}
}
В этой реализации обратите внимание на первую строку, где InstanceContextModeустановлен на PerCall. По умолчанию используется PerSession.
Это перечисление имеет три параметра:
PerCall - новый экземпляр InstanceContext, используемый для каждого вызова, независимого от Session
PerSession - новый экземпляр, используемый для каждого сеанса
Single - один экземпляр InstanceContext, используемый для всех клиентов.
Я создал клиента, который использует NetTcpBinding для соединения со службой:
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);
TCPCallbackHandler - это класс в клиенте, который реализует контракт обратного вызова в виде:
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();
}
}
ToПосмотрите поведение InstanceContext, я запустил службу, а затем запустил двух клиентов с каждой операцией перечисления, как обсуждалось выше.Вот результаты:
1 - PerCall
Клиент 1: urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 5 -urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 5
Клиент 2: urn: uuid: e101d2a7-ae41-4929-9789-6d43abf97f01 5 -urn: uuid: e101d2a7-ae41-4929-9789-6d43abf97f01 5
Здесь - urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 - это SessionId
Поскольку для каждого клиента Add вызывается дважды в клиенте, а в PerCall -> новый экземпляр InstanceContext создается при каждом вызове, мы создаем новый экземпляр ServiceClass для обоих вызовов каждого клиента.Следует отметить, что новый экземпляр создается даже для того же сеанса
// Первый вызов метода Add контракта
client.Add (val1); -> Создан новый экземпляр ServiceClass, и значение будет увеличено до 5
// Второй вызов метода Add контракта
client.Add (val2); -> Создан новый экземпляр ServiceClass, и значение будет увеличено до 5
2 - PerSession
Клиент 1: urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 5 - urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 10
Клиент 2: urn: uuid: e101d2a7-ae41-4929-9789-6d43abf97f01 5 - urn: uuid: e101d2a7-ae41-4929-9789-6d43abf97f01 10
Здесь экземпляр ServiceClass является отдельным для обоих клиентов, поскольку у них запущены разные сеансы. Таким образом, приращение вызовов составляет 0 -> 5 -> 10 (для обоих клиентов отдельно)
3 - одноместный
Клиент 1: urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 5 - urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 10
Клиент 2: urn: uuid: e101d2a7-ae41-4929-9789-6d43abf97f01 15 - urn: uuid: e101d2a7-ae41-4929-9789-6d43abf97f01 20
Здесь один и тот же экземпляр ServiceClass является общим для всех клиентов, поэтому у нас в первом клиенте 0 -> 5 -> 10. Второй клиент будет увеличиваться в том же экземпляре, поэтому мы получаем 10 -> 15 -> 20.
Это будет вести себя по-разному в соответствии с вызовом и может дать результат, как при одновременном вызове с клиентов.
Клиент 1: urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 5 - urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 15
Клиент 2: urn: uuid: e101d2a7-ae41-4929-9789-6d43abf97f01 10 - urn: uuid: e101d2a7-ae41-4929-9789-6d43abf97f01 20
Надеюсь, это поможет!