Повторно использовать клиентский класс в WCF после его сбоя - PullRequest
9 голосов
/ 01 мая 2009

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

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

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

Ответы [ 4 ]

16 голосов
/ 01 мая 2009

Как только объект 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
}
5 голосов
/ 01 мая 2009

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

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

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

Удачи

4 голосов
/ 01 мая 2009

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

  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, но оно отлично подходит для работы с прокси. Затем вы можете поместить несколько вызовов службы в одно и то же лямбда-выражение и передать его в метод.

0 голосов
/ 01 мая 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...