博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

.net 1.1中的Cache访问方式

Posted on 2012-11-20 09:28  love楠  阅读(334)  评论(0编辑  收藏  举报

在.net中引入了Cache借以提高程序执行效率.在程序里使用使用这Cache时可以使用三种方式:

  • HttpRuntime.Cache
  • Page.Cache
  • HttpContext.Current.Cache

我们主要讨论这三种方式到底有什么不同.

  首先,在查看Cache的定义时,可以发现,这三个类的Cache是同一个东西.这就表示,不论你使用那种方法在服务器端建立一个缓存,利用其它两种方式都是可以访问到的.实践一下就知道了.

首先,在一页面设置缓存,如下代码

   if ( Page.Cache["PageCache"] == null )
   {
    Page.Cache.Insert("PageCache","This is PageCache") ;

    Response.Write( "设置成功!<br>" ) ;
   }

   if ( HttpContext.Current.Cache["HttpCache"] == null )
   {
    HttpContext.Current.Cache.Insert("HttpCache","This is HttpCache");

    Response.Write( "设置成功!<br>" ) ;
   }

   if ( HttpRuntime.Cache["HttpRuntimeCache"] == null )
   {
    HttpRuntime.Cache.Insert("HttpRuntimeCache" , "This is HttpRuntimeCache" ) ;

    Response.Write( "设置成功!<br>" ) ;
   }

然后,在另一页面通过不同的方式来访问这些已经设置过的缓存.如下代码:

   Response.Write( "第一部分:<br>" ) ;

   Response.Write( "----利用HttpContext.Current返回的HttpContext访问通过Page.Cache设置的缓存:" ) ;

   if ( HttpContext.Current.Cache["PageCache"] != null )
   {
    Response.Write( "其值为:" +HttpContext.Current.Cache["PageCache"].ToString() +"<br>") ;
   }
   else
   {
    Response.Write( "没有访问到!<br>") ;
   }


   Response.Write( "----利用HttpRuntime.Cach访问通过Page.Cache设置的缓存:" ) ;

   if ( HttpRuntime.Cache["PageCache"] != null )
   {
    Response.Write( "其值为:" +HttpRuntime.Cache["PageCache"].ToString() +"<br>") ;
   }
   else
   {
    Response.Write( "没有访问到!<br>") ;
   }


   Response.Write( "第二部分:<br>" ) ;

   Response.Write( "----利用HttpContext.Current返回的HttpContext访问通过HttpRuntime设置的缓存:" ) ;

   if ( HttpContext.Current.Cache["HttpRuntimeCache"] != null )
   {
    Response.Write( "其值为:" +HttpContext.Current.Cache["HttpRuntimeCache"].ToString() +"<br>") ;
   }
   else
   {
    Response.Write( "没有访问到!<br>") ;
   }


   Response.Write( "----利用Page.Cach访问通过HttpRuntime.Cache设置的缓存:" ) ;

   if ( Page.Cache["HttpRuntimeCache"] != null )
   {
    Response.Write( "其值为:" +Page.Cache["HttpRuntimeCache"].ToString() +"<br>") ;
   }
   else
   {
    Response.Write( "没有访问到!<br>") ;
   }

 

   Response.Write( "第三部分:<br>" ) ;

   Response.Write( "----利用HttpRuntime.Cache访问通过HttpContext.Current.Cache设置的缓存:" ) ;

   if ( HttpRuntime.Cache["HttpCache"] != null )
   {
    Response.Write( "其值为:" +HttpRuntime.Cache["HttpCache"].ToString() +"<br>") ;
   }
   else
   {
    Response.Write( "没有访问到!<br>") ;
   }


   Response.Write( "----利用Page.Cach访问通过HttpContext.Current.Cache设置的缓存:" ) ;

   if ( Page.Cache["HttpCache"] != null )
   {
    Response.Write( "其值为:" +Page.Cache["HttpCache"].ToString() +"<br>") ;
   }
   else
   {
    Response.Write( "没有访问到!<br>") ;
   }

  执行的结果与之前的设想是一样的.那么这几种访问缓存的方式到底有什么不一样呢?看下面的代码!

方法一:访问HttpContext.Current.Cache

  private void OutHttpContextCacheToString()
  {
   try
   {
    if ( HttpContext.Current.Cache["HttpCache"] != null )
    {
     Response.Write( HttpContext.Current.Cache["HttpCache"].ToString() + "<br>" ) ;
    }
    else
    {
     Response.Write( "没有访问到缓存或缓存没有设置!<br>" ) ;
    } 
   }
   catch
   {
    Response.Write( "发生错误!<br>" ) ;
   }   
  }

方法二:访问Httpruntime.Cache

  private void OutHttpRumtimeCacheToString()
  {
   if ( HttpRuntime.Cache["HttpRuntimeCache"] != null )
   {
    Response.Write( HttpRuntime.Cache["HttpRuntimeCache"].ToString() + "<br>" ) ;
   }
   else
   {
    Response.Write( "没有访问到缓存或缓存没有设置!<br>" ) ;
   }               
  }

  上面的两个方法是通过两种不同的方式去读取缓存.如果你是在程里直接使用的话,程序是正常的.如果利用线程去调用这两个方法来读取缓存的话,会有什么结果呢?见下的代码:
 
   Response.Write( "利用线程通过HttpContext.Current.Cache来访问缓存中的数据,访问结果为:<br>" ) ;
   Thread TestThreadHttpContext = new Thread( new ThreadStart( OutHttpContextCacheToString ) ) ;
   TestThreadHttpContext.Priority = ThreadPriority.Highest ;
   TestThreadHttpContext.Start() ;

   Response.Write( "利用线程通过HttpRuntime.Cache来访问缓存中的数据,访问结果为:<br>" ) ;
   Thread TestThreadHttpRuntime = new Thread( new ThreadStart( OutHttpRumtimeCacheToString ) ) ;
   TestThreadHttpRuntime.Priority = ThreadPriority.Highest ;
   TestThreadHttpRuntime.Start() ;
 
  在查看结果的时候,你会发现,在执行过程中有错误发生了(通过跟踪代码也可以发现错误).错误发生在线程调用OutHttpContextCacheToString()方法中.而通过线程去调OutHttpRumtimeCacheToString()方法时却一切正常.为什么通过线程去调用OutHttpContextCacheToString()方法时会发生错误呢?这其实就是两种HttpRumtime与HttpContext访问缓存的不同之处.
  
  查看微软的MSDN文档,HttpContext的定义为"封装有关个别 HTTP 请求的所有 HTTP 特定的信息",而HttpRuntime的定义为"为当前应用程序提供一组 ASP.NET 运行时服务",换句话说,一个为是与特定Http请求相关联的,一个是与整个应用程序相关联.找到问题的的在了吗?
 
  我们知道,每一个Http请求都会产生一个HttpContext的实例,该实例可以通过HttpContext的Current属性来获取.该实例包含了当前Http请求的相关上下文信息.如果你对程序进行跟踪,你就会发现,当利用新线程访问HttpContext.Current.Cache时,程序报错,错误并不是发生在Cache,而是发生在HttpContext.Current,因为HttpContext.Current这个属性此时返回的null.为什么会这样?因为调用者并不是当前Http请求,而是一个新的Thread,HttpContext只是与当前Http请求相关(只与当前Http请求对应的线程相关),所以,当利用新的Thread通过HttpContext来访问缓存时,HttpContext.Current因无法从新Thread中获取HttpContext类型实例的上下文信息而返回null,此时,对一个为null的对象进行引用操作时,程序就会报错.
(注:即使把OutHttpContextCacheToString ()方法的错误处理语句去掉,程也不会抛异常,该异常只能在跟踪代码时检查到)
 
  到了这里,我们已经HttpRuntime与HttpContext的区别了.区别就是,HttpRuntime在任何地方都可以使用,而HttpContext则不一定.
 
  尽管结果可能让人有点失望,因为它们只有这么一点区别(我所知道的),但了解这一点是有好处的.最起码你知道了不能脱离当前Http请求而去访问HttpContext.Current属性.