.net 如何修复出现故障的WCF通道?

.net 如何修复出现故障的WCF通道?,.net,wcf,faulted,.net,Wcf,Faulted,当单个ClientBase实例用于多个WCF服务调用时,它可能会使通道进入故障状态(即服务关闭时) 我想在服务再次启动时自动修复通道。我找到的唯一方法是在每次方法调用之前调用以下代码: if (clientBase.InnerChannel.State == CommunicationState.Faulted) { clientBase.Abort(); ((IDisposable)clientBase).Dispose(); clientBase = ne

当单个
ClientBase
实例用于多个WCF服务调用时,它可能会使通道进入故障状态(即服务关闭时)

我想在服务再次启动时自动修复通道。我找到的唯一方法是在每次方法调用之前调用以下代码:

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

我觉得这样做不对。有谁有更好的主意吗?

你不能。一旦通道出现故障,它将永远出现故障。您必须创建一个新频道。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();
        }
    }
}
公共静态类服务,其中T:class,ICommunicationObject,new()
{
公共静态无效自动修复(参考T公司)
{
自动修复(ref-co,()=>newt());
}
公共静态无效自动修复(参考T co,Func createMethod)
{
if((co!=null)&&(co.State==CommunicationState.Faulted))
{
co.Abort();
co=null;
}
如果(co==null)
{
co=createMethod();
}
}
}
然后,您可以通过以下方式调用服务:

Service<SampleServiceClient>.AutoRepair(ref service,
    () => new SampleServiceClient(someParameter));
service.SomeMethod();
Service.AutoRepair(参考服务、,
()=>新的SampleServiceClient(someParameter));
service.SomeMethod();
或者,如果要使用默认的无参数构造函数,只需:

Service<SampleServiceClient>.AutoRepair(ref service);
service.SomeMethod();
Service.AutoRepair(参考服务);
service.SomeMethod();
由于它还处理服务为
null
的情况,因此在调用它之前不需要初始化服务


差不多是我能提供的最好的了。也许其他人有更好的方法。

这是我目前正在做的,但我也不能说这是最好的选择

我在调用中捕获异常时重新创建代理

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();
}

永远不要捕获系统异常,尤其是如果您没有抛出。该树包括
OutOfMemoryException
StackOverflowException
等实例。另外,你没有正确处理这里的旧频道。明白。这只是一个简单的例子。您是否看到了让通道被收集而不是显式地处理它的大问题?我假设我们在放弃之前不会重试这个操作1000次。@Scott P:ClientBase类中似乎没有调用
Close
Abort
的终结器,因此我想说,是的,如果您从未调用
Dispose
(或
Close
Abort
),这是一个问题; 它可能正在泄漏网络资源。是否也需要实现IDisposable?@DavidGardiner:如果它实现了
ICommunicationObject
,则不需要。WCF频道上的
Dispose
实现实际上是问题的一部分。@DavidGardiner:
Dispose
方法不应该出现在我的示例中,我删除了它。在通信对象上调用
Dispose
被充分证明是错误的,因为当您实际想要在故障(如上所述)上调用
Abort
时,它只在内部调用
Close
。除非您正在实现自己的通信对象,否则您不需要在此处关注
IDisposable
。在感谢中有一个更详细的例子。实际上co=null,抛出异常并建议用default(co)替换null。我确实取消了对该行的注释。@swiscoder:在这种情况下,您可能需要将
class
约束添加到泛型定义中。无需更改代码,因为没有实现
ICommunicationObject
的结构。