.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
的结构。