13

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

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

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

我觉得这不是正确的做法。有人有更好的主意吗?

4

2 回答 2

21

你不能。一旦一个通道发生故障,它就会永远发生故障。您必须创建一个新频道。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您无需在调用服务之前对其进行初始化。

几乎是我能提供的最好的。也许其他人有更好的方法。

于 2010-01-05T19:32:18.533 回答
1

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

当调用中捕获到异常时,我会重新创建代理。

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();
}
于 2010-01-05T19:45:59.080 回答