Как предотвратить прекращение работы службы WCF из-за исключения канала?

Я создал одноэлементную службу WCF с netNamedPipeBinding. Когда возникает исключение канала, он оставляет канал в неисправном состоянии, и все последующие операции вызывают исключения. Как я могу предотвратить это? Я хочу, чтобы исключение TimeoutException или любое другое распространенное исключение приводило к сбою только одной операции и не заставляло службу отвечать.


person Jader Dias    schedule 24.12.2009    source источник
comment
Вы уверены, что канал обслуживания перестает отвечать в случае ошибки? Я все время использую одноэлементные службы на очень большом сайте, и у меня никогда не было проблемы, о которой вы описываете.   -  person nitzmahone    schedule 25.12.2009
comment
У меня есть журналы, в которых говорится, что канал непригоден для использования, потому что он находится в неисправном состоянии.   -  person Jader Dias    schedule 25.12.2009


Ответы (2)


Вам нужно обернуть исключения на стороне сервера в FaultException. Если вы контролируете оба конца провода, и оба конца являются .NET, вы можете просто обернуть исключение .NET в FaultException<T> и отправить его обратно клиенту. Таким образом, канал останется пригодным для использования.

Дополнительную информацию см. В разделе Определение и устранение ошибок в контрактах и ​​услугах в MSDN. плюс ознакомьтесь с этой статьей о CodeProject и этим сообщением в блоге Зачем использовать WCF FaultException на том же тема.

Кроме того, чтобы облегчить себе жизнь, ознакомьтесь с интерфейсом IErrorHandler., который можно реализовать на стороне сервера для глобального перехвата исключений и преобразования их в сбои. Также просмотрите множество сообщений в блогах по этой теме, например IErrorHandler: универсальный конвертер ошибок или многие другие (Bing или Google для большего).

Чтобы сделать вашу жизнь еще проще, вы можете реализовать IErrorHandler как поведение, которое вы можете включить или выключить в своей службе - либо в конфигурации службы, либо установив атрибут в своем классе обслуживания. В Интернете довольно много реализаций, одна из которых мне нравится: Полезное поведение WCF: IErrorHandler.

person marc_s    schedule 24.12.2009
comment
также нашел другое решение, см. мой ответ - person Jader Dias; 04.01.2010
comment
Интересно, что мои службы перестали работать, когда я реализовал свое решение, поэтому мне пришлось реализовать ваши, чтобы вернуть их в нормальное состояние. - person Jader Dias; 05.01.2010
comment
Я обнаружил проблему в своем решении, нам не следует удалять каналы, потому что они сложны, см. stackoverflow.com/questions/2008382/ - person Jader Dias; 06.01.2010

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

Это немного сложно, потому что вы не должны удалять канал, кроме того, что он является 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);
});
person Jader Dias    schedule 04.01.2010
comment
Думаю, здесь есть ошибка: channel и proxy - это одно и то же. Я думаю, вам следует заменить proxy на channel. - person Andrey K.; 03.09.2018