ASP.NET 客户端应用程序中的 WCF ChannelFactory 和 Channel 缓存

Posted

技术标签:

【中文标题】ASP.NET 客户端应用程序中的 WCF ChannelFactory 和 Channel 缓存【英文标题】:WCF ChannelFactory and Channel caching in ASP.NET client application 【发布时间】:2010-12-22 00:15:57 【问题描述】:

我正在构建一系列将被多个应用程序使用的 WCF 服务。因此,我正在尝试定义一个通用库来访问 WCF 服务。

知道不同用户发出的每个服务请求都应该使用不同的通道,我正在考虑缓存每个请求的通道 (HttpContext.Current.Items) 并缓存用于为每个应用程序创建通道的 ChannelFactory (HttpApplication.Items),因为我可以使用相同的ChannelFactory 创建多个频道。

但是,在关闭 ChannelFactory 和 Channel 时,我对这种缓存机制有疑问。

    我是否需要在使用通道后、请求结束时关闭通道,或者当请求的上下文终止时是否可以将通道关闭 (?)? ChannelFactory 怎么样?由于每个通道都与创建它的 ChannelFactory 相关联,因此在应用程序进程 (AppDomain) 的生命周期内保持相同的 ChannelFactory 是否安全?

这是我用来管理这个的代码:

public class ServiceFactory

    private static Dictionary<string, object> ListOfOpenedChannels
    
        get
        
            if (null == HttpContext.Current.Items[HttpContext.Current.Session.SessionID + "_ListOfOpenedChannels"])
            
                HttpContext.Current.Items[HttpContext.Current.Session.SessionID + "_ListOfOpenedChannels"] = new Dictionary<string, object>();
            

            return (Dictionary<string, object>)HttpContext.Current.Items[HttpContext.Current.Session.SessionID + "_ListOfOpenedChannels"];
        
        set
        
            HttpContext.Current.Items[HttpContext.Current.Session.SessionID + "_ListOfOpenedChannels"] = value;
        
    

    public static T CreateServiceChannel<T>()
    
        string key = typeof(T).Name;

        if (ListOfOpenedChannels.ContainsKey(key))
        
            return (T)ListOfOpenedChannels[key];
        
        else
        
            ChannelFactory<T> channelF = new ChannelFactory<T>("IUsuarioservice");
            T channel = channelF.CreateChannel();
            ListOfOpenedChannels.Add(key, channel);
            return channel;
        
    

谢谢!

【问题讨论】:

【参考方案1】:

最好在完成后立即关闭频道。这会将其放回通道池中,以便其他工作线程使用。

是的,通道工厂(昂贵的部分)可以在应用程序的整个生命周期内保留。


更新

从 .Net 4.5 开始,有一个内置的工厂缓存选项 ChannelFactory Caching .NET 4.5

【讨论】:

+1 准确 - 缓存“昂贵”部分 - ChannelFactory - 但根据需要创建通道并尽早关闭/处置 好人,所以如果我在应用程序的生命周期内只缓存一个 ChannelFactory 并在所有通道创建中重用它,我就不会有问题,对吧? 每种服务类型一个渠道工厂,正确。这样你就不必在每次调用时都进行所有反射和类型创建,这就是为什么为了性能你不应该使用 VS 生成的代理,因为类是 gens 每次调用都使用一个新工厂。 “你不应该使用 VS 生成的代理,因为类是 gens 每次调用都会使用一个新工厂” - 根据最后的链接,特定问题已通过 .NET 3.5 解决,因此ChannelFactory 缓存在 ClientBase 中。 blogs.msdn.com/wenlong/archive/2007/10/27/… @Xiaofu:确实ClientBase&lt;T&gt;在某些情况下会使用ChannelFactory&lt;T&gt;上的MRU缓存。如果EndpointClientCredentials 被更改或者Binding 以编程方式定义,它将不会缓存ChannelFactoy。有一种方法可以通过将 CacheSettings 设置为 CacheSettings.AlwaysOn 来强制缓存 ChannelFactory。 msdn.microsoft.com/en-us/library/hh314046(v=vs.110).aspx【参考方案2】:

这是一个旁白。为什么使用 SessionID 作为上下文键?每个请求的 context.Items 都是唯一的。那就是:

HttpContext.Current.Items[HttpContext.Current.Session.SessionID +"_ListOfOpenedChannels"]

在功能上应该等同于:

HttpContext.Current.Items["ListOfOpenedChannels"]

【讨论】:

我在发布这个问题后意识到这一点。最终结果在这里:github.com/tucaz/CommunicationsManagerThanks

以上是关于ASP.NET 客户端应用程序中的 WCF ChannelFactory 和 Channel 缓存的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET 网站 + Windows 窗体应用程序 + WCF 服务:客户端凭据

使用 SignalR、WCF 双工服务和 ASP.Net 通用处理程序向客户端推送通知?

ASP.NET 中的 WCF 模拟异常

ASP.net Webservice *.asmx 访问与 WCF 服务参考

强大的自托管服务器的最佳选择:WCF 与 ASP.NET Web Api

从 ASP.NET 应用程序验证 WCF 服务