2009-05-01 2 views
9

Я использую WCF для системы клиентских серверов. Когда я добавляю служебную ссылку на IService на сервере, создается класс ServiceClient класса proxy. Мой код выглядит следующим образом:Повторное использование класса клиента в WCF после его устранения

ServiceClient client = new ServiceClient(); 
try 
{ 
    client.Operation1(); 
} 
catch(Exception ex) 
{ 
    // Handle Exception 
} 
try 
{ 
    client.Operation2(); 
} 
catch(Exception ex) 
{ 
    // Handle Exception 
} 

Проблема заключается в том, что если есть исключение связи в первом вызове, изменения состояния клиента к Faulted, и я не знаю, как восстановить его, чтобы сделать второй звонок. Есть ли способ открыть его? или я должен создать новый и заменить экземпляр (это не похоже на элегантный способ)?

ответ

0

Это, скорее всего, вызвано необработанным исключением на стороне сервера. Время выполнения WCF по умолчанию прерывает ваш экземпляр службы и помещает канал в состояние сбоя в случае необработанного исключения, и вы больше не можете обмениваться данными по этому каналу. Поэтому вам нужно будет создать новый сеанс с сервисом. Вы должны перехватывать исключения на стороне сервера и отправлять ошибки мыла, поднимая исключение FaultException или определяя FaultContract. Существует также свойство returnUnknownExceptionsAsFaults, которое вы можете использовать.

16

Как только объект ICommunicationObject (ваш клиентский объект WCF) находится в неисправном состоянии, единственный способ «повторно открыть» его - создать новый.

ServiceClient client = new ServiceClient(); 
try 
{ 
    client.Operation1(); 
} 
catch(Exception ex) 
{ 
    if (client.State == CommunicationState.Faulted) 
    { 
      client.Abort(); 
      client = new ServiceClient(); 
    } 
} 
try 
{ 
    client.Operation2(); 
} 
catch(Exception ex) 
{ 
    // Handle Exception 
} 
+0

Проблема заключается в том, что у нас есть внутренняя функция, которая получает делегата функции на прокси-сервере службы и многократно выполняет эту функцию до тех пор, пока не будет выбрано исключение связи (наша реализация для автоматического повторного подключения). Таким образом, в этом решении функция создаст экземпляр прокси для каждой попытки выполнения и ему придется возвращать обновленный экземпляр вызывающему, поэтому он не будет иметь закрытый прокси ... Вид уродливого: -/ – Andy

5

Если есть исключение связи по первому зову, который вызывает неисправное состояние, вы должны в основном «воссоздать» клиент прокси WCF. В вашем примере я бы, вероятно, сделать что-то вроде:

if (client.State == CommunicationState.Faulted) 
    client = new ServiceClient(); 

Это позволит вам «повторно открыть» соединение, если он неисправен. Это может показаться немного излишним, но если вы получаете исключение связи на стороне клиента, то, вероятно, что-то еще (например:? Сервер мертвый сервер не отвечает)

Успехов

3

согласен с последние ответы, после неудачи, вам нужно отменить. Мы используем комбинацию лямбды и способ, как в следующем, чтобы сделать это:

public static void Use<TServiceInterface>(TServiceInterface proxy, Action handler) 
    { 
    Type proxyType = typeof(TServiceInterface); 
    IClientChannel channel = (IClientChannel)proxy; 

    try 
    { 
     handler(); 

     _logSource.Log(LogLevel.Debug, string.Format("Closing client channel for '{0}' ...", proxyType.Name)); 

     channel.Close(); 

     _logSource.Log(LogLevel.Debug, string.Format("Client channel for '{0}' closed.", proxyType.Name)); 
    } 
    catch 
    { 
     if (channel.State == CommunicationState.Faulted) 
     { 
      _logSource.Log(LogLevel.Debug, string.Format("Aborting client channel for '{0}' ...", proxyType.Name)); 

      channel.Abort(); 

      _logSource.Log(LogLevel.Debug, string.Format("Client channel for '{0}' aborted.", proxyType.Name)); 
     } 
     else 
     { 
      _logSource.Log(LogLevel.Debug, string.Format("Closing client channel for '{0}' ...", proxyType.Name)); 

      channel.Close(); 

      _logSource.Log(LogLevel.Debug, string.Format("Client channel for '{0}' closed.", proxyType.Name)); 
     } 

     throw; 
    } 
    } 

Это небольшое изменение решения, которое уже на .net, но работает отлично подходит для работы с прокси. Затем вы можете поместить несколько вызовов службы в одно и то же lambda-выражение и передать его в метод.

+1

В предлагаемом решении вы всегда закрываете канал после первого использования, и это может привести к плохой производительности или даже неправильной работе при использовании сеанса. Также странно, что функция, которая не создает канал, закрывает его. – Andy

+0

Метод выше действует как оператор using в C#. Вы правы, что он вызывает близко после выполнения действия обработчика, но я думаю, что вам не хватает того, что в действии обработчика может быть бесконечное число операторов. Вы можете сделать 15 звонков на интерфейс службы, если хотите. Кроме того, я не считаю, что странно, что функция не делает все это. Чаще всего разделять строительство и уничтожение объекта на отдельный метод или отдельные сегменты кода. Заводы обычно не берут на себя ответственность за очистку объектов, которые они создают – 2009-07-28 18:57:15

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