0

因为我在几个小时内找不到我的问题的适当答案,所以我把它贴在这里。

我有一个带有共享接口 (IService) 库和动态创建的代理(使用 CreateChannel 创建)的 WPF/WCF 应用程序。主要问题是代理没有被关闭/处置,我在第 200 次服务调用时遇到了这个异常:

系统达到了为油门“MaxConcurrentSessions”设置的限制。此限制设置为 200。可以通过修改 serviceThrottle 元素中的属性“maxConcurrentSessions”或通过修改行为 ServiceThrottlingBehavior 的“MaxConcurrentSessions”属性来更改限制值。

有趣的是,相同的代理可以与 BasicHttpBinding 一起正常工作!

似乎 NetNamedPipeBinding 代理没有自动关闭和处置。以下是一些客户端代码片段。

// creation of ChannelFactory - only one for each service interface
public static ChannelFactory<T> CreateChannelFactory(string serviceAddress)
{
    Binding binding = new NetNamedPipeBinding()
    {
        // setting quotas and timeouts                
    };            

    ChannelFactory<T> factory = new ChannelFactory<T>(binding, new EndpointAddress(serviceAddress));

    factory.Endpoint.Behaviors.Add(new AuthenticationBehavior()); // custom IEndpointBehavior

    foreach (OperationDescription op in factory.Endpoint.Contract.Operations)
    {
        DataContractSerializerOperationBehavior dataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>() as DataContractSerializerOperationBehavior;
        if (dataContractBehavior != null)
        {
            dataContractBehavior.MaxItemsInObjectGraph = 2147483647;
        }
    }                                     

    return factory;
}

public static T GetService()
{
    // simplified - actually holding a collection of CFs and creating each factory only once
    return ChannelFactoryHelper<T>.CreateChannelFactory(serviceAddress).CreateChannel();
}

// creation of the proxy - new for each WCF call
IService svc = ServiceHelper<IService>.GetService();    
... // calling the service

你可以看到我没有使用“using”语句,因为代理没有实现 IDisposable。第一个问题是,我该怎么做。在客户端,我使用 IService 作为代理类型。如果我想让 IService 成为 IDisposable,我必须在服务端实现 dispose 方法——因为我的 Service 实现了 IService。这似乎不合逻辑 - 调用服务方法来处理该服务......

由于最好不要将服务调用的所有代码更改为“使用”:有没有办法在不再使用代理时自动处理代理?为什么不自动完成?请注意,我正在使用自定义 IExtensionBehavior - 这可能是原因吗?

任何帮助,将不胜感激。谢谢!

4

1 回答 1

0

首先,您会发现从该CreateChannel方法返回的服务代理对象确实实现了IDisposable,因为IClientChannel派生自IDisposable。但是,您不应使用标准 using 块来利用此功能,因为如果在您使用通道时出现故障,则在右括号中可能会发生难以诊断的异常。

与在每个服务代理类型的包装器中显式地实现 IDisposable 相比,您可能会发现以下模式的一些变体是一种改进。您可以在接受委托 ( Action<IService>) 的通用函数中实现该模式,以执行“调用服务”位。

IService svc;
try
{
    // creation of the proxy - new for each WCF call
    svc = ServiceHelper<IService>.GetService();    
... // calling the service
    myDelegateDoingStuffWithService(svc);
}
finally
{
    try
    {
        ((ICommunicationObject)svc).Close();
    }
    catch (CommunicationException ex)
    {
        ((ICommunicationObject)svc).Abort();
    }
}
于 2013-08-15T15:29:22.377 回答