Я создал одноэлементную службу WCF с netNamedPipeBinding. Когда возникает исключение канала, он оставляет канал в неисправном состоянии, и все последующие операции вызывают исключения. Как я могу предотвратить это? Я хочу, чтобы исключение TimeoutException или любое другое распространенное исключение приводило к сбою только одной операции и не заставляло службу отвечать.
Как предотвратить прекращение работы службы WCF из-за исключения канала?
Ответы (2)
Вам нужно обернуть исключения на стороне сервера в FaultException. Если вы контролируете оба конца провода, и оба конца являются .NET, вы можете просто обернуть исключение .NET в FaultException<T>
и отправить его обратно клиенту. Таким образом, канал останется пригодным для использования.
Дополнительную информацию см. В разделе Определение и устранение ошибок в контрактах и услугах в MSDN. плюс ознакомьтесь с этой статьей о CodeProject и этим сообщением в блоге Зачем использовать WCF FaultException на том же тема.
Кроме того, чтобы облегчить себе жизнь, ознакомьтесь с интерфейсом IErrorHandler., который можно реализовать на стороне сервера для глобального перехвата исключений и преобразования их в сбои. Также просмотрите множество сообщений в блогах по этой теме, например IErrorHandler: универсальный конвертер ошибок или многие другие (Bing или Google для большего).
Чтобы сделать вашу жизнь еще проще, вы можете реализовать IErrorHandler как поведение, которое вы можете включить или выключить в своей службе - либо в конфигурации службы, либо установив атрибут в своем классе обслуживания. В Интернете довольно много реализаций, одна из которых мне нравится: Полезное поведение WCF: IErrorHandler.
Есть другой способ. Вы можете создать экземпляр клиентского прокси для каждого запроса вместо использования одного экземпляра для нескольких запросов. Таким образом, если канал переходит в неисправное состояние, он все равно отбрасывается.
Это немного сложно, потому что вы не должны удалять канал, кроме того, что он является IDisposable.
Не получится:
using(var channel = channelFactory.CreateChannel())
{
return channel.ServiceMethod(parameter);
}
Вместо этого вам следует:
public static class Service<T>
{
public static ChannelFactory<T> _channelFactory = new ChannelFactory<T>("");
public static TResult Use<TResult>(Func<T, TResult> func)
{
TResult output;
var channel = (IClientChannel)_channelFactory.CreateChannel();
bool success = false;
try
{
output = func((T)proxy);
channel.Close();
success = true;
}
finally
{
if (!success)
{
proxy.Abort();
}
}
return output;
}
}
return Service<IService>.Use(channel =>
{
return channel.ServiceMethod(parameter);
});
channel
и proxy
- это одно и то же. Я думаю, вам следует заменить proxy
на channel
.
- person Andrey K.; 03.09.2018