Нужно ли закрывать эталонный клиент службы .NET, когда я его использую? - PullRequest
16 голосов
/ 14 июля 2010

Я пытаюсь выяснить, необходимо ли закрывать эталонный клиент службы .net, когда вы его используете.Кажется, почти все примеры, с которыми я сталкивался в сети, но сгенерированный клиент реализует IDisposable, и, поскольку он открывает соединение со службой, моя интуиция подсказывает мне, что вам нужно закрыть это соединение, когда выс этим покончено.

Вот пример кода, который я извлек из http://msdn.microsoft.com/en-us/library/bb386386(v=VS.90).aspx:

private void button1_Click(System.Object sender, System.EventArgs e)
{
    ServiceReference1.Service1Client client = new 
        ServiceReference1.Service1Client();
    string returnString;

    returnString = client.GetData(textBox1.Text);
    label1.Text = returnString;
}

Я думаю, что вы должны хотя бы вызвать client.Close () вконец этого метода, а еще лучше обернуть первую строку в операторе using.Я просто хотел получить некоторую обратную связь по этому вопросу, чтобы узнать, каковы лучшие практики.

Ответы [ 3 ]

22 голосов
/ 14 июля 2010

Да, вы делаете, но вы должны быть очень осторожны при этом. При закрытии всего, что реализует ICommunicationObject, существует вероятность того, что утилизация объекта займет слишком много времени в случае ошибки или сбоя в канале.

Из-за этого предписано, что вы вызываете метод Close , а затем вызываете метод Dispose для IDisposable, используя несколько перехватов для определенных типов исключений и вызывая Abort прежде чем вы, наконец, позвоните Dispose.

Вы можете заключить эту логику в реализацию IDisposable, которую можно использовать в операторе using.

Ключом здесь является создание токена, который реализует IDisposable, а затем в этой реализации вызовите Close, перехватите соответствующие исключения, вызовите Abort (при необходимости) и затем вызовите Dispose.

Это реализовано как метод расширения, который возвращает IDisposable для него, что, в свою очередь, позволяет использовать его в операторе using.

4 голосов
/ 14 июля 2010

Рекомендуется, если класс реализует IDisposable, вызывать Dispose() в предложении finally или заключить его в using () { }

Edit
ПослеКомментарий casperOne ниже, похоже, к клиентам WCF следует относиться более осторожно.Я этого не знал, и меня это немного беспокоит, поскольку использование () до сих пор хорошо мне помогало.

0 голосов
/ 14 июля 2010

Лучше всего посмотреть на сгенерированный клиентский код для Dispose() и посмотреть, действительно ли он избавляется от чего-либо, например, HTTP-соединений или чего-то еще.

С одной стороны, может случиться так, что реализуемый им интерфейс наследует от IDisposable, потому что некоторый клиент может должен что-то распоряжаться, даже если этот конкретный не делает.Это похоже на MemoryStream , класс, который реализует IDisposable, потому что все Stream s делают, но на самом деле не имеет дело с неуправляемыми ресурсами.

С другой стороны, онникогда не повредит использовать using, даже если Dispose() - пустой метод.И примеры MS на самом деле действительно плохи о том, что они не используют using, даже если они должны (например, здесь ), поэтому не принимайте их пример как хорошее доказательство того, что вам не нужнок.

...