如何治愈故障的WCF频道?

Jad*_*ias 12 .net wcf faulted

当单个ClientBase<T>实例用于多个WCF服务调用时,它可以使通道进入故障状态(即,当服务停止时).

当服务再次出现时,我想自动修复频道.我找到的唯一方法是在每次方法调用之前调用以下代码:

if (clientBase.InnerChannel.State == CommunicationState.Faulted)
{
      clientBase.Abort();
      ((IDisposable)clientBase).Dispose();
      clientBase = new SampleServiceClientBase();
}
Run Code Online (Sandbox Code Playgroud)

我觉得这不是正确的做法.谁有更好的主意?

Aar*_*ght 20

你不能.一旦渠道出现故障,它就会出现故障.您必须创建一个新频道.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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用以下内容调用您的服务:

Service<SampleServiceClient>.AutoRepair(ref service,
    () => new SampleServiceClient(someParameter));
service.SomeMethod();
Run Code Online (Sandbox Code Playgroud)

或者,如果您想使用默认的无参数构造函数,只需:

Service<SampleServiceClient>.AutoRepair(ref service);
service.SomeMethod();
Run Code Online (Sandbox Code Playgroud)

由于它还处理服务的情况,因此null在调用服务之前无需初始化服务.

几乎是我能提供的最好的.也许别人有更好的方法.

  • @DavidGardiner:“Dispose”方法不应该出现在我的示例中,我删除了它。在通信对象上调用“Dispose”已被充分证明是错误的,因为当您实际上想在发生故障时调用“Abort”时,它只是在内部调用“Close”(如上所述)。除非您正在实现自己的通信对象,否则您不需要在这里关心“IDisposable”。我写的拦截器实现中有一个更详细的示例(https://github.com/Aaronaught/Convolved.Hosting/blob/master/Convolved.Hosting/RestartOnFaultInterceptor%601.cs) (2认同)