8

自从我几年前开始编写经典的 ASP 12 (左右)以来,我一直在考虑这个问题,但我从来没有找到一个很好的解决方案,因为 ASP 和 ASP.NET 的体系结构一直是一个糟糕的实践,魔法共享单身人士等。我最大的问题是HttpApplication对象及其非事件事件(Application_Start,Application_End等)。

如果您想在 HTTP 应用程序的整个生命周期内只做一次事情,Application_Start那么显然是这样做的地方。对?不完全是。首先,这本身不是一个事件,它是一个神奇的命名约定,当遵循它时,会导致每个由 IIS 创建的 AppDomain 调用一次该方法。

除了魔术命名约定是一种可怕的做法之外,我开始认为这可能是对象上不存在Start事件这样的事情的原因HttpApplication。因此,我尝试了确实存在的事件,例如Init. 好吧,这也不是一个真正的事件,它是一个可覆盖的方法,这是次优的。

似乎Init()每次实例化对象都会调用该方法,HttpApplication每个 AppDomain 不止一次发生这种情况。这意味着我不妨把我的启动逻辑放在HttpApplication对象的构造函数中。

现在我的问题是,为什么我不应该将我的启动逻辑放在构造函数中?为什么甚至Init()存在,我需要关心Application_Start吗?如果我这样做了,谁能解释为什么HttpApplication对象中的这个伪事件没有适当的事件或可覆盖的方法?

任何人都可以向我解释为什么在一个典型的 ASP.NET 应用程序中,创建了 8 个 my 实例HttpApplication(当然,这会导致构造函数和Init运行多次;这可以通过锁定和一个名为 的共享静态布尔值来缓解initialized)当我的应用程序只有一个 AppDomain 时?

4

3 回答 3

5

Asp.Net 运行时保留一个 HttpApplication 对象池。每个 .aspx 请求都由从池中分配的单个对象处理(在您的情况下为 8 个对象)。

您的问题的答案,确实调用了 Application_Start 事件,但仅针对 HttpApplication 的第一个实例,而不是后续的,因此您可以确保在启动应用程序或重新启动 IIS 的应用程序池时只调用一次. Application_OnEnd 事件(最后一个实例)也是如此

同时,在 HttpApplication 对象的每个实例上调用 Init() 和 Dispose()。这将在每个实例(即每个请求)上调用。

他们为什么这样做..?也许是为了平衡性能和内存优化。

希望我回答了你的问题。

于 2010-07-23T13:06:18.040 回答
3

在第一次创建 HttpApplication 实例时调用 Application_Start,但在后续实例上不调用似乎有点 hack。也许微软不想向那些不想知道的人解释静态构造函数的概念。

然而,Application_End() 似乎是必需的,因为没有 C# 等效的静态析构函数/终结器。随着黑客的发展,这还不错。只是闻起来有点好笑。

于 2011-05-31T02:13:34.057 回答
0

为每个并发请求创建一个 HttpApplication 对象。也就是说,ASP.NET 创建的每个线程都有自己的 HttpApplication 实例。实例被重用于后续请求,其方式与从线程池中重用线程的方式相同。

使用 Init 方法初始化 HttpApplication 上的实例字段,因为如果在 Application_Start 事件中完成,这些字段只会在第一个实例中被初始化。

于 2010-07-23T12:39:00.823 回答