Почему важно удалить/закрыть клиентский прокси-сервер WCF

Я слышал, что необходимо удалить (или закрыть) клиентский прокси-сервер WCF, даже если

  • вы не используете сеансы
  • нет неуправляемых ресурсов, требующих детерминированной очистки (например, открытых сокетов)

Например, при использовании BasicHttpBinding с конфигурацией привязки по умолчанию это должно работать даже на популярной веб-странице, верно?

var clt = new MyServiceClient();
clt.PlaceOrder(foo);
// no dispose

or

var clt = new ChannelFactory<IOrderService>().CreateChannel();
clt.PlaceOrder(foo);

Спасибо


person ConfusedNoob    schedule 25.08.2011    source источник
comment
Я полагаю, вы могли бы позволить сборщику мусора сделать это за вас, но это просто не чистый код. Вы объявляете это, вы освобождаете его. Основы, которым, кажется, больше не учат.   -  person Brad Christie    schedule 25.08.2011


Ответы (3)


Создание ChannelFactory и открытие — это дорогостоящая операция, и вам следует избегать ее выполнения для каждого вызова, если вы заботитесь о производительности.

Ваш первый вариант использования неверен даже с basicHttpBinding, потому что он потенциально может создать новую фабрику каналов для каждого экземпляра. В .NET 3.5 SP1 реализовано кэширование ChannelFactory, так что в определенных сценариях все будет в порядке.

Во втором случае использования, если вы кешируете и повторно используете фабрику каналов, удаление на самом деле не обязательно, но имейте в виду, что вы/ваш специалист по развертыванию можете изменить время привязки @ развертывания, а отсутствие закрытия/удаления может иметь огромное влияние.

Таким образом, всегда безопасно закрывать/утилизировать, и поэтому MSDN предлагает это.

person zamd    schedule 25.08.2011

Хорошая практика — закрывать вещи (и избавляться от них), когда с ними покончено. (Вы бы оставили файловый поток открытым, даже если вы выполняете чтение/запись в него/из него?) Навскидку, я вижу несколько причин:

  1. Сервер (может/будет) иметь ограниченное количество активных подключений, которые он поддерживает. Чем раньше вы избавитесь от своей услуги, тем раньше следующий клиент сможет использовать этот слот. (Зачем ждать тайм-аута, если вы на самом деле закончили?)
  2. Избегайте избыточных накладных расходов из-за неактивного соединения. Предоставленных ресурсов в наши дни «множество», но чем меньше накладных расходов вы сохраните, тем выше будет ваша производительность в конце концов.
  3. Вы снижаете риск ошибок/исключений из-за тайм-аута, избавляясь от клиента, когда он завершится.
  4. Закрыв его, когда вы закончите, вы эффективно сохраните журналы сервера в чистоте. В конце концов, даже если клиент этого не показывает, сервер может столкнуться с исключениями тайм-аута, отображаемыми в журнале из-за бездействующих соединений, о которых не позаботились, когда они должны были быть.
  5. MSDN говорит (обратите внимание на 4-й маркер в списке объектов клиента WCF) .

Только некоторые из причин, которые приходят мне в голову.

person Brad Christie    schedule 25.08.2011
comment
Закрытие соединения — это не то же самое, что удаление соединения. - person Kirk Broadhurst; 25.08.2011
comment
@Kirk: Согласен, но также проверьте, нет ли ошибок, иначе следует выполнить прерывание. - person Brad Christie; 25.08.2011
comment
пара замечаний - файловая система представляет собой неуправляемые ресурсы. Прокси в вопросе нет. Вопрос действительно в том, «почему» и потому, что это аккуратно или потому, что MSDN говорит, что это не то, что я искал. Вы говорите, что Dispose закрывает открытое соединение (даже для basicHttpBinding) и поэтому вы должны это делать? Благодарность - person ConfusedNoob; 26.08.2011
comment
@ConfusedNoob: обработка файлов была аналогией, а не сравнением. И я упомянул MSDN последним, потому что, хотя это и указано, это не очень хорошая причина (но реализации, представленные авторами пакетов, всегда являются хорошим указанием на то, как вам следует действовать). - person Brad Christie; 26.08.2011
comment
@KirkBroadhurst: в стандартной библиотеке .NET, если метод Close() вообще существует, часто это просто псевдоним для Dispose() или наоборот. Это также относится к ClientBase<TChannel>, от которого произошли клиенты WCF, и в документации даже указано, что удаление клиента закрывает его. Если вы хотите правильно обрабатывать объекты IDisposable, вы всегда можете просто использовать метод Dispose и вообще забыть о Close, так как он лишний. - person Matti Virkkunen; 26.04.2017
comment
Прокси-серверы @ConfusedNoob могут представлять неуправляемые ресурсы. Сокет неуправляемый, поэтому используется привязка MSMQ, которая фактически записывает ваши сообщения в файл. - person Tanveer Badar; 29.11.2019

Это действительно зависит от типа клиента. Например, если вы пишете приложение ASP.NET, которое вызывает службу, рекомендуется кэшировать прокси-сервер, поскольку его создание обходится дорого.

При этом, как только вы закончите с любым ресурсом IDisposable, вы должны удалить его, чтобы удаляемый объект получил возможность освободить ресурсы, которые он удерживает, чтобы его можно было удалить из памяти. Если у объекта IDisposable есть метод Close, его следует вызывать первым.

Прекрасную статью на эту увлекательную тему можно найти здесь: http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

person Philippe    schedule 25.08.2011