您的位置:首页 > 理论基础 > 计算机网络

ASP.NET 3.5核心编程学习笔记(32):HttpApplicationState

2011-04-24 10:34 537 查看
  ASP.NET提供了4个层面上的状态管理工具:应用程序、会话、页面和请求,每层都有专用的容器对象。

应用程序的状态

  下表总结了各状态对象的主要功能:



  尽管HttpApplicationState和HttpSessionState对象与ASP内部对象Application和Session的名称不同,但在状态方面,它们的功能完全一致。

  HttpApplicationState对象可使应用程序中的所有请求处理程序获得一种字典形式的存储对象。所有HTTP处理程序和模块都能够存储和检索应用程序字典中的值。应用程序状态只在当前应用程序的上下文中可见,位于同一系统中的其他应用程序无法访问或更改其中的值。

  当客户端首次请盐浓度某个虚拟目录中的资源时,HttpApplicationState类的实例会被创建。每个运行中的应用程序都持有自身的全书状态对象。访问应用程序状态最常见的方法是通过Page对象的Application属性。应用程序状态不能在Web Farm和Web Garden中共享。

HttpApplicationState类的属性

  HttpApplicationState类是封闭的,继承于NameObjectCollectionBase类。为方便使用,HttpApplicationState类被设计为键/值对集合,其中键为String类型,值为Object类型。在内部,基类会使用HashTable,初始容量为0,并按需要自动增加。

  下表列出了HttpApplicationState类的属性:



  注意,静态对象和实际的状态值存储在不同的集合中,该静态集合的类型为HttpStaticObjectsCollection。

HttpApplicationState类的方法

  HttpApplicationState类的方法大多是普通键/值集合相应方法的特殊化版本。如下表所示,其显著的扩展涉及一种锁定机制,旨在应对状态值的连续访问:





  注意,GetEnumerator方法继承于一个集合类,但这个类没有实现锁定机制。如果通过该方法对集合进行枚举,返回值只是通过调用NameObjectCollectionBase的get方法来获取的。因此,这种枚举过程不是线程安全的。枚举集合内容更好的方式是,通过while语句和Get方法来访问每一项。此外,我们还可以在执行枚举前以手动方式对集合进行锁定。

状态同步

  HttpApplicationState上的所有操作都需要某种同步措施,以便确保同一应用程序中运行的多个线程能安全的访问集合中的值,而不会造成死锁和访问冲突。写入方法(如Set和Remove)和Item属性的set访问器会在执行操作前隐式地应用写入锁。Lock方法能够确保只有当前线程能够更改应用程序状态。

  我们不必用Lock/Unlock方法将单个Set、Clear或Remove包装起来,这些方法已经是线程安全的了。但如果需要屏蔽多个不能并发写入的指令,则需显式地使用Lock方法。

//锁定
Application.Lock();
int val = (int)Application["MyValue"];
if(val < 10)
Application["MyValue"] = val + 1;
Application.UnLock();


  我们应该成对使用Lock和UnLock。然而,如果遗漏了UnLock,导致死锁的可能性并不大。因为,.NET Framework会在请求结束、超时或出现未处理异常时自动将锁移除。因此,为处理该异常,可考虑使用finally块来清除锁。

应用程序状态的权衡

  若不使用HttpApplicationState对象,则可以在global.asax文件中添加公共成员。与HttpApplicationState集合中的数据项相比,全局成员有一定的优越性,因为全局成员是强类型的,且不需要HashTable来定位某个值。但另一方面,全局变量本身不具备同步功能,必须以手动方式进行保护。我们不得不使用Lock来保护对这些成员的访问。

内存占用

  在存储全局数据时,无论选择何种方式来存储应用程序的全局状态,都应注意一些基本事项。

  全局数据存储会导致持久性的内存占用,如果不通过代码显式地将其移除,那么应用程序全局状态中存储的数据只有在应用程序关闭后才会被移除。因此,在需要全局共享数据时,有必要使用Cache对象。存储在ASP.NET Cache中的数据会被自动清理,能够确保在数据对虚拟内存待占用率较高时自动将其清除。

数据的并发访问

  由于锁定机制,存储全局数据还有很多问题有待解决。对应用程序状态的锁定,很容易变成性能瓶颈。应用程序全局状态存储在内存中,而不会逾越计算机的边界。在多计算机和多处理器的环境下,应用程序全局状态仅局限在运行于某台计算机或某个CPU的工作进程中。因此,它并不是名符其实的“全局”。此外,由于进程运行被终止(简单地讲是ASP.NET进程被回收),那些内存中的数据也会受到影响。如果要在Web Farm或Web Garden环境下使用应用程序状态功能,最好将全局状态存储在数据库表中,至少应将全局数据封装在某个“智能”的代理对象中。通过该对象对数据的存在性进行检查,若出于某种原因而导致数据丢失,该对象要重新填充。如下所示:

public object GetGlobalData(string entry)
{
object o = Application[entry];
//检查数据是否存在
if(o == null)
{
//重新获取数据
......
//返回数据
return Application[entry];
}
return o;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: