Ну, это много вопросов вместе, и ситуация действительно немного сложна.Когда вы создаете клиента, вы можете сделать это либо через ссылку на службу и получить класс, полученный из ClientBase<ServiceContract>
, либо вы можете использовать ChannelFactory<ServiceContract>
и создавать каналы вручную (в первом случае внутренне используется ChannelFactory).
Как это относится к вашему вопросу?Давайте сначала посмотрим на настоящее соединение TCP.Когда вы определяете NetTcpBinding
, вы можете установить его MaxConnections
свойство (по умолчанию 10).Это свойство определяет номер пула соединения.Это означает, что если вы создаете клиентский канал на сервере и закрываете канал, соединение не прерывается немедленно.Он остается открытым в пуле, пока он не будет использован другим открытым клиентским каналом для того же сервера или пока не истечет время его простоя.Вы можете открыть столько соединений, сколько позволяет сервер, но после закрытия соответствующих клиентских каналов будет объединено только число, определенное MaxConnections
.Другие соединения будут разорваны немедленно.Если вы создаете CustomBinding
, вы можете использовать транспорт TCP напрямую, где вы также можете контролировать время простоя (я думаю, по умолчанию 2 минуты).Соединения объединяются до тех пор, пока соответствующий ChannelFactory
не будет уничтожен = используйте один ChannelFactory
для приложения (ClientBase
сделайте это внутренне).
Теперь давайте поговорим о самом канале, потому что он связан с вашим другимвопросы.WCF отличается сессионными и бессессионными каналами.TcpTransportChannel
является сессионным.Это означает, что, открыв канал, вы создаете сеанс.Сеанс означает, что все запросы от одного клиентского прокси-сервера по умолчанию всегда обслуживаются одним и тем же экземпляром службы (для каждого экземпляра сеанса).Но экземпляр по умолчанию однопоточный.Это означает, что вы можете иметь несколько потоков, используя один и тот же прокси, но служба будет обрабатывать запросы в последовательном порядке.Если вы хотите, чтобы ваш сервис обрабатывал несколько запросов одновременно, вы должны пометить его [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple]
.Как только вы это сделаете, вы несете ответственность за многопоточную обработку в службе (несколько потоков обращаются к одному экземпляру службы).
Сессионные каналы имеют один большой недостаток.Любой сбой или исключение в службе нарушит работу канала, и вы, как правило, узнаете об этом после повторной попытки использования канала (исключение говорит о том, что канал находится в состоянии сбоя и не может использоваться).Вы должны всегда правильно обрабатывать эти ситуации, и вы должны правильно закрывать каналы / прокси, если вы не хотите их использовать, или прервать их, если они неисправны.Неисправный канал не может быть восстановлен - он должен быть прерван, и вы должны создать новый прокси / канал.Я не уверен, возвращаются ли соединения в пул, если вы этого не сделаете.
Повторное использование прокси / канала зависит от типа приложения, которое вы создаете.Я определенно не буду повторно использовать прокси / канал для нескольких запросов в веб-приложении, но повторное использование абсолютно нормально в WinForm или WPF-приложении.
Редактировать:
Да ClientBase
использует ChannelFactory
внутренне.Способ использования ChannelFactory
со временем изменился.В .NET 3.0 фабрика была создана для каждого экземпляра ClientBase
.Начиная с .NET 3.5 WCF использует внутренний кэш MRU (используется в последнее время), который кэширует до 32 последних использованных фабрик.Чтобы воспользоваться этим кэшированием, вы должны использовать прокси-конструктор без параметров или с endpointConfigurationName
и remoteAddress
/ EndpointAddress
.Вы не должны создавать конечную точку в коде - эти прокси не используют кеш.Подробнее о теме здесь .