Как лечить неисправные каналы WCF? - PullRequest
12 голосов
/ 05 января 2010

Когда один экземпляр ClientBase<T> используется для нескольких вызовов службы WCF, он может перевести канал в неисправное состояние (т. Е. Когда служба не работает).

Я бы хотел излечить канал автоматически, когда служба снова заработает. Единственный найденный способ - вызывать следующий код перед каждым вызовом метода:

if (clientBase.InnerChannel.State == CommunicationState.Faulted)
{
      clientBase.Abort();
      ((IDisposable)clientBase).Dispose();
      clientBase = new SampleServiceClientBase();
}

Мне показалось, что это не правильный способ сделать это. У кого-нибудь есть идея получше?

Ответы [ 2 ]

20 голосов
/ 05 января 2010

Вы не можете. Как только канал неисправен, он неисправен навсегда. Вы должны создать новый канал. Каналы WCF имеют состояние (в некотором смысле), поэтому неисправный канал означает, что состояние может быть повреждено.

То, что вы можете сделать, это поместить используемую логику в служебный метод:

public static class Service<T> where T : class, ICommunicationObject, new()
{
    public static void AutoRepair(ref T co)
    {
        AutoRepair(ref co, () => new T());
    }

    public static void AutoRepair(ref T co, Func<T> createMethod)
    {
        if ((co != null) && (co.State == CommunicationState.Faulted))
        {
            co.Abort();
            co = null;
        }
        if (co == null)
        {
            co = createMethod();
        }
    }
}

Затем вы можете вызвать свою службу со следующими данными:

Service<SampleServiceClient>.AutoRepair(ref service,
    () => new SampleServiceClient(someParameter));
service.SomeMethod();

Или, если вы хотите использовать конструктор по умолчанию без параметров, просто:

Service<SampleServiceClient>.AutoRepair(ref service);
service.SomeMethod();

Поскольку он также обрабатывает случай, когда служба null, вам не нужно инициализировать службу перед вызовом.

Практически лучшее, что я могу предложить. Может быть, у кого-то есть лучший способ.

1 голос
/ 05 января 2010

Это то, чем я сейчас занимаюсь, но я не могу сказать, что это лучший вариант.

Я воссоздаю прокси, когда в вызове обнаружена исключительная ситуация.

try
{
    ListCurrentProcesses();
}
catch (TypeLoadException ex)
{
    Debug.Print("Oops: " + ex.Message);
    m_Proxy = new ProcessManagerProxy();
}
catch (EndpointNotFoundException endpointEX)
{
    Debug.Print("Oops: " + endpointEX.Message);
    m_Proxy = new ProcessManagerProxy();
}
catch (CommunicationException communicationEx)
{
    Debug.Print("Oops: " + communicationEx.Message);
    m_Proxy = new ProcessManagerProxy();
}
...