"Application 这是Web应用程序生命期中的全局保存区,保存在Application中的数据是全局有效的;在Asp.Net中,有一个应用程序池,其中保存了数个(或数十个)应用程序实例,每一次请求都会从池中取一个实例来处理请求"
    这个结论是错误的,对于web应用程序来说,一个web应用程序有且只有一个HttpApplicationState对象,这个对象是在第一个用户第一次访问该web应用程序的任意url时由asp.net框架创建的,而且这个实例是唯一的,是客户不可创建的,所以你的所谓的关于Application的论断是错误的,请在贴子之前考虑清楚,这里有许多初学者,不要误导了他们!具体细节请参照MSDN.

解决方案 »

  1.   

    你好
    "在Asp.Net中,有一个应用程序池,其中保存了数个(或数十个)应用程序实例,每一次请求都会从池中取一个实例来处理请求"你可能有些误会了,可能是我说的不明白,我没有说HttpApplicationState有多个实例,而是HttpApplication,也就是Global.asax定义的应用程序的对象,而不是保存数据的HttpContext的Application属性;对应HttpContext的属性,应该是ApplicationInstance我是深入研究了MSDN和Asp.Net的源代码才这样说的,实际上你可以想想,如果只有一个实例来处理请求,那么这个对象会面临很复杂的线程访问的处理,因为对服务器来说,同一个时间里面会有很多请求同时产生,如果只使用一个Application实例来处理请求,那么会造成很严重的堵塞;实际上,Asp.Net内部会有一个ApplicationFactory的类,有这个类来维护应用程序池,针对每一个请求来获取一个实例处理它。
    这一段话是从MSDN中摘录下来的:
    “此类的实例是在 ASP.NET 基础结构中创建的,而不是由用户直接创建的。一个实例在其生存期内被用于处理多个请求,但它一次只能处理一个请求。这样,成员变量才可用于存储针对每个请求的数据。”
    ms-help://MS.VSCC/MS.MSDNVS.2052/cpref/html/frlrfsystemwebhttpapplicationclasstopic.htm对于HttpApplicationState,的确只有一个实例,它是HttpApplicationFactory类的一个属性,针对整个应用程序是唯一的;我是没有说清楚这二者的差异,谢谢你的提醒。
      

  2.   

    实际上可能是因为Asp.Net的命名有一些混乱,造成一些困扰但是也没办法,主要是为了向后兼容,虽然HttpContext.Application看起来就是应用程序的对象,但实际它不是,它只是一个保存数据的全局Hashtable,这样命名主要是为了保持和Asp的兼容,它是HttpApplicationState类型。在Asp.Net里面,Web应用程序的对象的类是HttpApplication,在一次请求中,可以通过HttpContext.ApplcationInstance来获得应用程序的实例,这个实例是存在于应用程序池的,在应用程序生存期始终会留在池里,它可能会处理很多请求,但是一次只能处理一个,从请求开始到请求结束都不能替换。HttpContext.Application -> HttpApplicationState
    HttpContext.ApplicationInstace -> HttpApplication这样的命名的确很不容易区分
    :)
      

  3.   

    不敢苟同,如你所说,asp.net维护一个对象池,而这池中的对象都指向同一个HttpApplicationState,那会造成同步这些对象得更复杂的问题,因为这些对象都指向同一个,你说是不是?
        另外,你说的只有一个对象会造成多线程同步复杂,我不明白,会复杂在哪里?我不知道你的这些资料是从哪里的来的,如果你像确切的了解asp.net对象中具体包括了那些对象,办法有一个,就是在内存窗口中观察。
        “此类的实例是在 ASP.NET 基础结构中创建的,而不是由用户直接创建的。一个实例在其生存期内被用于处理多个请求,但它一次只能处理一个请求。这样,成员变量才可用于存储针对每个请求的数据。”
         这句话恰恰说明你的观点是不正确的,你的观点是同时能处理多个请求,可上面的话却说一次只能处理一个,不知是我没弄懂你的意思,还是你根本就没领会上面的话的意思?
        你后面谈到呢基本正确,希望你能掌握足够的证据之后在给下定义。
      

  4.   

    不好意思
    "如果你像确切的了解asp.net对象中具体包括了那些对象,办法有一个,就是在内存窗口中观察"
    你知道IL吗?知道怎么反编译吗?
    ApplicationFactory这个类在MSDN中是找不到的,只能通过反编译之后查看源代码,我是看过之后再结合MSN才得出结论,我可以告诉你,我不会无根据的说这些结论,我的结论都是基于事实的,建议你反编译查看Asp.Net的源代码再来讨论。"另外,你说的只有一个对象会造成多线程同步复杂,我不明白,会复杂在哪里?"
    如果你弄不懂这句话我也没办法,实际上一个请求进来之后,ApplicationFactory会从池中获取一个应用程序实例来处理该请求,再请求结束之前,这个实例不能再处理其他请求,如果允许处理其他请求,那么就会面临实例字段的多线程处理,如果进行大量的Lock操作会降低效率,而且必须要维护不同线程的状态,所以Asp.Net的做法不是Lock某个实例字段,而是Lock整个实例。“此类的实例是在 ASP.NET 基础结构中创建的,而不是由用户直接创建的。一个实例在其生存期内被用于处理多个请求,但它一次只能处理一个请求。这样,成员变量才可用于存储针对每个请求的数据。”  -MSDN
    “在Asp.Net里面,Web应用程序的对象的类是HttpApplication,在一次请求中,可以通过HttpContext.ApplcationInstance来获得应用程序的实例,这个实例是存在于应用程序池的,在应用程序生存期始终会留在池里,它可能会处理很多请求,但是一次只能处理一个,从请求开始到请求结束都不能替换。"  -我说的上面这两段话这两段话难道表达的不是一个意思?
    “你的观点是同时能处理多个请求”  我不知道你的结论是怎么得来的,希望你看清楚我的回复在说。
      

  5.   

    “在应用程序的生存期中,ASP.NET 维护一系列 Global.asax 导出的 HttpApplication 实例。当应用程序接收到 HTTP 请求时,ASP.NET 页框架将分配这些实例中的一个来处理该请求。该特定的 HttpApplication 实例负责管理它所分配到的请求的整个生存期,并且只有在完成该请求后才可以再次使用该实例。"-MSDN
      

  6.   

    ms-help://MS.VSCC/MS.MSDNVS.2052/cpguide/html/cpconworkingwithhttpapplicationinstances.htm
      

  7.   

    这是HttpApplicationFactoy中获取一般应用程序的方法的源代码,可能原始代码的变量名称和这里的有些不同,局部变量反编译之后是没有名称的,为了方便看,我自己命了名称。private HttpApplication GetNormalApplicationInstance(HttpContext context) 
    {
    HttpApplication app; //这次要返回的应用程序实例
    Stack appStack; app = null;
    lock (this._freeList) //因为_freeList是实例字段,所以需要Lock保证线程同步
    if (this._numFreeAppInstances > 0) // 如果空闲实例数量大于0
    {
    app = (HttpApplication) this._freeList.Pop();//从空闲实例的堆栈中获取一个实例
    this._numFreeAppInstances = this._numFreeAppInstances - 1;//空闲实例计数器递减
    }
    if (app == null) //如果没有获取到
    {
    app = (HttpApplication) HttpRuntime.CreateNonPublicInstance(this._theApplicationType);//动态创建一个实例,HttpRuntime.CreateNonPublicInstance实际上会调用Activator.CreaateInstance,_theApplicationType就是Global.asax中的类型
    app.InitInternal(context, this._state, this._eventHandlerMethods); //初始化该实例
    }
    return app;
    }这就是证据
      

  8.   

    “不敢苟同,如你所说,asp.net维护一个对象池,而这池中的对象都指向同一个HttpApplicationState,那会造成同步这些对象得更复杂的问题,因为这些对象都指向同一个,你说是不是?”asp.net维护一个对象池,而这池中的对象都指向同一个HttpApplicationState
    这是事实,的确,这样会面临同步的问题,所以MSDN中建议Global中不要使用实例字段,尽量使用静态字段,因为使用实例字段的话,那么两次请求之间可能会面临不同的应用程序实例,也许它们的某个实例字段的值不一样:
    "Init 方法与 Application_OnStart 事件不同,因为总是对应用程序中的所有 HttpApplication 实例调用该方法。在应用程序的生存期中只调用一次 Application_OnStart,这便是对 HttpApplication 的第一个实例调用。使用 Application_OnStart 只是为了创建或修改所有管线实例共享的状态,例如 ApplicationState 对象的使用。因为局部变量不被多个 HttpApplication 实例共享,所以不要使用它来创建局部变量。紧接着销毁 HttpApplication 类的实例之前调用 HttpApplication.Dispose 方法。您可以使用它来清理任何本地资源。Dispose 方法与 Application_OnEnd 事件不同,因为总是对应用程序中所有 HttpApplication 实例调用该方法。在应用程序的生存期中只引发一次 Application_OnEnd,这便是对被强行停止 HttpApplication 的最后一个实例引发。使用 Application_OnEnd 只是为了清理所有管线实例共享的状态或资源,例如 ApplicationState 对象的使用。因为局部变量不被多个 HttpApplication 实例共享,所以不要使用它来清理局部变量。
    "ms-help://MS.VSCC/MS.MSDNVS.2052/cpguide/html/cpconworkingwithhttpapplicationinstances.htm这是MSDN中对 HttpApplication 类的Init和Dispose方法的建议,其中“局部变量不被多个 HttpApplication 实例共享”这一句就是对你对同步应用程序对象的疑惑的解释,实际Asp.Net做了很简单的方法来处理,也就是根本就不同步实例字段,所以它也建议了,如果要保存全局的数据,使用Global中的局部变量是不可以的,使用HttpApplicationState才是正确选择