Исключение в операторе "using", когда WCF не закрывает соединения должным образом. Как закрыть неисправные клиентские соединения WCF или соединения с исключениями?
В Stackru есть несколько вопросов, касающихся закрытия соединений WCF, однако ответы с самым высоким рейтингом относятся к этому блогу:
http://marcgravell.blogspot.com/2008/11/dontdontuse-using.html
У меня проблема с этой техникой, когда я устанавливаю точку останова на сервере и позволяю клиенту зависать более одной минуты. (Я намеренно создаю исключение тайм-аута)
Проблема в том, что клиент "зависает" до тех пор, пока сервер не завершит обработку. Я предполагаю, что все очищается после исключения.
Что касается TimeOutException
кажется, что retry()
логика клиента будет продолжать повторять отправку запроса на сервер снова и снова, где я вижу, как отладчик на стороне сервера выстраивает очереди в очередь запросов, а затем выполняет каждый запрос в очереди одновременно. Мой код не ожидал, что WCF будет действовать таким образом, и это может быть причиной проблем с повреждением данных, которые я вижу.
Что-то не совсем совпадает с этим решением.
Каков всеобъемлющий современный способ борьбы с ошибками и исключениями в прокси WCF?
2 ответа
Обновить
По общему признанию, это - немного мирского кода, чтобы написать. В настоящее время я предпочитаю этот связанный ответ и не вижу в этом коде "хаков", которые могут вызвать проблемы в будущем.
Это рекомендуемый Microsoft способ обработки вызовов клиента WCF:
Для более подробной информации смотрите: Ожидаемые исключения
try
{
...
double result = client.Add(value1, value2);
...
client.Close();
}
catch (TimeoutException exception)
{
Console.WriteLine("Got {0}", exception.GetType());
client.Abort();
}
catch (CommunicationException exception)
{
Console.WriteLine("Got {0}", exception.GetType());
client.Abort();
}
Дополнительная информация Так много людей задают этот вопрос на WCF, что Microsoft даже создала специальный образец, чтобы продемонстрировать, как обрабатывать исключения:
C:\WF_WCF_Samples\WCF\Basic\Client\ExpectedExceptions\CS\ клиент
Учитывая, что существует так много проблем, связанных с оператором использования (горячие?) Внутренние обсуждения и темы по этому вопросу, я не собираюсь тратить свое время, пытаясь стать ковбоем кода и найти более чистый путь. Я просто смирюсь с этим и реализую клиенты WCF таким подробным (но доверенным) способом для моих серверных приложений.
Необязательные дополнительные ошибки, чтобы поймать
Многие исключения происходят из CommunicationException
и я не думаю, что большинство из этих исключений следует повторить. Я пролистал каждое исключение в MSDN и нашел короткий список исключений, которые можно повторить (в дополнение к TimeOutException
выше). Дайте мне знать, если я пропустил исключение, которое следует повторить.
Exception mostRecentEx = null;
for(int i=0; i<5; i++) // Attempt a maximum of 5 times
{
try
{
...
double result = client.Add(value1, value2);
...
client.Close();
}
// The following is typically thrown on the client when a channel is terminated due to the server closing the connection.
catch (ChannelTerminatedException cte)
{
mostRecentEx = cte;
secureSecretService.Abort();
// delay (backoff) and retry
Thread.Sleep(1000 * (i + 1));
}
// The following is thrown when a remote endpoint could not be found or reached. The endpoint may not be found or
// reachable because the remote endpoint is down, the remote endpoint is unreachable, or because the remote network is unreachable.
catch (EndpointNotFoundException enfe)
{
mostRecentEx = enfe;
secureSecretService.Abort();
// delay (backoff) and retry
Thread.Sleep(1000 * (i + 1));
}
// The following exception that is thrown when a server is too busy to accept a message.
catch (ServerTooBusyException stbe)
{
mostRecentEx = stbe;
secureSecretService.Abort();
// delay (backoff) and retry
Thread.Sleep(1000 * (i + 1));
}
catch(Exception ex)
{
throw ex; // rethrow any other exception not defined here
}
}
if (mostRecentEx != null)
{
throw new Exception("WCF call failed after 5 retries.", mostRecentEx );
}
Закрытие и удаление службы WCF
Как упоминается в этом сообщении, вы закрываете, когда не было исключений, и прерываете, когда возникают ошибки. Dispose
и поэтому Using
не должен использоваться с WCF.