2017-02-13 10 views
0

У меня есть веб-служба WCF, которая обращается к службе окон WCF на другой машине. Служба windows делает все данные доступными и передает результаты веб-службе. Я прочитал несколько статей об утилизации клиента службы для службы WCF правильно, но я не уверен, что лучший способ сделать это в веб-службе. (Если это помогает, веб-сервис PerCall не PerSession)Утилизация клиента службы WCF в веб-службе WCF

Это все, что я делаю прямо сейчас:

Public Class Service1 
    Implements IService1 

    Private p_oWindowsService As DataService.Service1Client 

    Public Sub New() 
    p_oWindowsService = New DataService.Service1Client 
    End Sub 

    Public Function GetData(ByVal value As Integer) As String Implements IService1.GetData 
    Return p_oWindowsService.GetData(value) 
    End Function 

    Public Function GetDataUsingDataContract(ByVal composite As CompositeType) As CompositeType Implements IService1.GetDataUsingDataContract 
    If composite Is Nothing Then 
     Throw New ArgumentNullException("composite") 
    End If 
    If composite.BoolValue Then 
     composite.StringValue &= "Suffix" 
    End If 
    Return composite 
    End Function 

Я не располагая клиент службы вообще прямо сейчас, от чего я «Мы читаем, что это серьезная проблема. Обходной я смотрю на что-то вроде этого внутри функции GetData:

Public Function GetData(ByVal value As Integer) As String Implements IService1.GetData 
    Using oWindowsService As New DataService.Service1Client 
     Return oWindowsService.GetData(value) 
    End Using   
    End Function 

Основе What is the best workaround for the WCF client `using` block issue?, я знаю, что я должен на самом деле не зависит от помощи блока. Но должен ли я создавать и удалять сервис-клиента в каждой функции? Это мой реальный вопрос.

спасибо.

ответ

2

Да, не используйте утилизацию. Делают это так:

var client = new ...; 
try { 
    // Do work 

    // Everything went well so close the client 
    client.Close(); 
} 
catch(Exception ex) { 
    // Something went wrong so call abort 
    client.Abort(); 

    // Other logging code 
} 

if(client.State != System.ServiceModel.CommunicationState.Closed) { 
    client.Close(); 
} 

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

Вы можете задаться вопросом, почему Abort в блоке catch? Причина в том, что:

Учитывая, что привязка WCF использует сеансы транспорта, клиент после сбоя даже не сможет его закрыть (если не было сеанса транспортного уровня, клиент мог использовать или закрыть прокси-сервер, но это не рекомендуется, так как конфигурация сеансов может измениться). Поэтому после того, как произошла ошибка, единственной безопасной операцией является прервать прокси-сервер.

См this больше на Abort против Close.


EDIT

В комментариях вы спросили:

ли вы рекомендуете создавать и закрывать клиент службы, как это в пределах каждой функции веб-службы вызывает службу Windows?

Нет, я не думаю, что это необходимо.Давайте посмотрим, вы вызываете службу WCF из веб-приложения (ASP MVC), то вы могли бы сделать что-то подобное в Dispose методе контроллера, так как ClientBase<TChannel> орудий ICommunicationObject:

protected override void Dispose(bool disposing) { 
    base.Dispose(disposing); 

    ServiceHelper.DisposeService((this._whateverServiceClient as ICommunicationObject)); 
} 

А вот ServiceHelper класс вы можете использовать в любом месте:

public static class ServiceHelper { 

    /// <summary> 
    /// Disposes the given service. 
    /// </summary> 
    /// <param name="service">The service.</param> 
    public static void DisposeService(ICommunicationObject service) { 

    if(service != null) { 

     bool abort = true; 

     try { 
      if(service.State == CommunicationState.Opened || service.State == CommunicationState.Opening) { 
       service.Close(); 
       abort = false; 
      } 
     } 
     finally { 

      // Determine if we need to Abort the communication object. 
      if(abort) 
       service.Abort(); 
     } 
    } 
    } 

}

идея была бы такой же, если вы называли его от другого клиента.

+0

Вы рекомендуете создавать и закрывать клиент службы как это внутри каждой функции веб-служба вызывает службу Windows? – cjw

+0

@ cjw См. Отредактированный ответ. – CodingYoshi

0

Вам не нужно явно избавиться клиента, как всегда, если вы на самом деле нужно, это один из способов правильного закрытия & утилизации вашего клиента:

 // use client 
     try 
     { 
      ((IClientChannel)client).Close(); 
     } 
     catch 
     { 
      ((IClientChannel)client).Abort(); 
     } 
     finally 
     { 
      ((IDisposable)client).Dispose(); 
     } 
+0

Вызов Dispose() в блоке finally запрашивает проблемы. Dispose() вызывает Close(), который может вызывать исключение, если канал неисправен. –

+0

Код, который я предоставил, безопасен в использовании и не будет выбрасывать. Если Close() выбрасывает, будет вызываться Abort(), который установит внутреннее состояние на «Закрыто». При вызове Dispose() Close() будет вызван снова с состоянием Closed, которое ничего не сделает. Как я уже сказал: вам не нужно явно распоряжаться клиентом, но если вам действительно нужно, приведенный выше код показывает безопасный способ сделать это. –

+0

Close() немедленно вернется, если объект ICommunicationObject находится в состоянии закрытия. Таким образом, объект ICommunicationObject все же может стать неисправным, после чего вызов Dispose() приведет к исключению. –

 Смежные вопросы

  • Нет связанных вопросов^_^