2009-08-06 6 views
14

У меня есть клиентское приложение, которое каждые 10 секунд пытается отправить сообщение через веб-службу WCF. Это клиентское приложение будет находиться на компьютере на борту корабля, который, как мы знаем, будет иметь пятнистую интернет-связь. Я хотел бы, чтобы приложение попыталось отправить данные через службу, и если это не удастся, поставить в очередь сообщения, пока они не смогут отправить их через службу.Восстановление из CommunicationObjectFaultedException в WCF

Чтобы проверить эту настройку, я запускаю клиентское приложение и веб-сервис (как на моем локальном компьютере), так и все работает нормально. Я пытаюсь имитировать плохое интернет-соединение, убивая веб-службу и перезагружая ее. Как только я убью службу, я начинаю получать CommunicationObjectFaultedExceptions - что ожидается. Но после перезагрузки службы я продолжаю получать эти исключения.

Я уверен, что есть что-то, что я не понимаю о парадигме веб-сервиса, но я не знаю, что это такое. Может ли кто-нибудь дать совет о том, возможна ли эта настройка, и если да, то как решить эту проблему (т. Е. Восстановить канал связи с веб-службой)?

Спасибо!

Клэй

ответ

33

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

Вы также должны убедиться, что вы правильно закрыли прокси-сервер службы. Прокси-сервер службы WCF может генерировать исключение при закрытии, и если это произойдет, соединение не будет закрыто, поэтому вы должны прервать. Используйте шаблон try {Close}/catch {Abort}. Также имейте в виду, что метод dispose вызывает close (и, следовательно, может вызывать исключение из dispose), поэтому вы не можете просто использовать подобное использование с обычными одноразовыми классами.

Например:

try 
{ 
    if (yourServiceProxy != null) 
    { 
     if (yourServiceProxy.State != CommunicationState.Faulted) 
     { 
      yourServiceProxy.Close(); 
     } 
     else 
     { 
      yourServiceProxy.Abort(); 
     } 
    } 
} 
catch (CommunicationException) 
{ 
    // Communication exceptions are normal when 
    // closing the connection. 
    yourServiceProxy.Abort(); 
} 
catch (TimeoutException) 
{ 
    // Timeout exceptions are normal when closing 
    // the connection. 
    yourServiceProxy.Abort(); 
} 
catch (Exception) 
{ 
    // Any other exception and you should 
    // abort the connection and rethrow to 
    // allow the exception to bubble upwards. 
    yourServiceProxy.Abort(); 
    throw; 
} 
finally 
{ 
    // This is just to stop you from trying to 
    // close it again (with the null check at the start). 
    // This may not be necessary depending on 
    // your architecture. 
    yourServiceProxy = null; 
} 

Существует блог статьи об этом here

+0

+10, если я мог - ничего себе, это поведение полностью под радаром, никогда не работал бы, что происходит если бы я не наткнулся на этот ответ. –

+0

Bravo! Я реализовал версию этого метода расширения: TryDispose в прокси-классе для использования другими. –

+0

@ Moby's Stunt Double - можете ли вы поделиться своим кодом? – RichardHowells