Application_Start和Application_OnStart之间的区别

46
我正在将ASP.NET MVC代码添加到一个预先存在的ASP.NET Webforms项目中。各种教程建议将路由添加到从Global.asax中的Application_Start()方法调用的方法中。我的Global.asax已经有一个带有一些设置代码的Application_OnStart(Object,EventArgs)方法。
如果我尝试同时使用Start和OnStart,那么OnStart不会被调用(而且设置失败,导致错误)。看起来我必须选择一个。
我的问题是:我应该使用哪一个?它们之间有什么区别?它们在不同的时间被调用吗?
(注意:在撰写本文时,“top three Google”的搜索结果无用或误导性。我希望Stack Overflow可以解决这个问题。)
3个回答

86
在经典的(遗留的)ASP中,有一些特殊的函数名,如果在您的global.asa文件中定义了,它们将在应用程序生命周期的指定点运行。 它们被定义为:
  • Application_OnStart-在您的应用程序收到第一个HTTP请求以及处理任何.ASP文件之前立即运行一次。
  • Application_OnEnd-在应用程序关闭期间运行一次,在处理完所有请求后。
  • Session_OnStart-在每个唯一用户会话的开始运行。 如果用户/客户端禁用了Cookie,则此会在每个请求上运行,因为ASP从未检测到会话Cookie来标识现有会话。
  • Session_OnEnd-(理论上!)每次用户会话过期时运行。祝你好运。

这些基本上是硬编码到经典ASP运行时中的 - 您无法更改它们,并且无法将任何其他方法附加到这些事件。

在ASP.NET中,有一个称为AutoEventWireup的东西,它使用反射查找符合特定命名约定的方法,并在响应由ASP.NET运行时引发的匹配事件时运行这些方法。最常见的例子是Page_Load方法,它会自动调用以响应页面生命周期中Page类触发的Load事件。

相同的技术用于附加处理程序到应用程序级别的生命周期事件。它会查找命名为ModuleName_EventName或ModuleName_OnEventName的方法,不带参数()(object sender, EventArgs e)

这里是有趣的部分-如果您定义了多个匹配方法,则只执行出现在文件中最新的方法。 (基本上是最后一个方法获胜)

因此,如果您的global.asax.cs看起来像这样:

public class Global : System.Web.HttpApplication {
    protected void Application_Start() {
        Debug.WriteLine("A: Application_Start()");
    }

    protected void Application_Start(object sender, EventArgs e) {
        Debug.WriteLine("B: Application_Start(object sender, EventArgs e)");
    }

    protected void Application_OnStart() {
        Debug.WriteLine("C: Application_OnStart()");

    }
    protected void Application_OnStart(object sender, EventArgs e) {
        Debug.WriteLine("D: Application_OnStart(object sender, EventArgs e)");
    }
}

如果你注释掉该块中的最后一个方法,你将在调试输出中看到消息C;如果不注释,则看到消息D。

所以,使用任何你喜欢的命名约定都可以,但是如果你定义多个,只有在源文件中最后出现的一个会被执行。我个人会坚持使用Application_Start(object sender, EventArgs e),因为这是由Visual Studio项目模板和大多数.NET设计/编码工具生成的签名。


非常好的解释,特别是不同的方法签名。 - Craig Walker
我对这个解释有一个问题。当你说“在任何.ASP文件被处理之前运行一次”时,这是否意味着该进程在服务器启动时运行还是在每个HTTP连接的开始时运行?如果是前者,那么是否可能实例化一个单例,可以运行一个应该在应用程序生命周期内运行的后台进程? - miken.mkndev
1
应用程序在收到HTTP请求之前不会运行。当请求到达时,IIS将启动应用程序进程,运行任何Application_Start事件,然后处理传入的请求。常见的部署脚本是部署应用程序的新版本,然后立即发出HTTP请求以启动应用程序-特别是如果Application_Start需要几秒钟才能完成。最好提前做这个动作,而不是惩罚那些恰好是部署后第一个访问者的不幸用户。 - Dylan Beattie
关于后台进程-虽然可能,但真的不推荐。请参考http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx/和http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx了解更多有关如何在ASP.NET应用程序中运行后台任务的讨论。 - Dylan Beattie

12
根据 Microsoft 关于 ASP.Net 应用程序生命周期的文档,你应该在 global.asax 文件中使用 Application_Start 方法:

Application_Start:当请求 ASP.NET 应用程序中的第一个资源(如页面)时调用。应用程序生命周期中只调用一次 Application_Start 方法。你可以使用此方法执行启动任务,例如将数据加载到缓存中并初始化静态值。

W3 学校介绍了 ASP (旧版本?)中更多关于 Application_OnStart 的内容。这个方法放在 Global.asa 文件中,而不是 Global.asax。

Application_OnStart:在创建第一个新会话之前(当首次引用 Application 对象时)触发 Application_OnStart 事件。将此事件放置在 Global.asa 文件中。

参见此答案的评论,其中建议 Application_OnStart 适用于旧版 ASP,而 Application_Start 适用于 ASP.NET。

1
我猜OnStart在ASP.NET/Global.asax中的作用只是为了向后兼容传统的ASP。我已经将我的应用程序切换到Start,目前还没有出现任何问题。谢谢! - Craig Walker

6

Application_OnStart:

Application_OnStart函数在处理任何 .asp 文件之前被调用,也就是在任何文本或图形被呈现并发送到用户浏览器之前。在此函数中,对 Active Server Pages Server 对象上的 CreateObject 方法进行以下调用,创建 CDO Rendering Library RenderingApplication 对象。如果此调用成功,则 objRenderApp 变量包含指向新对象的指针。

我找到的所有参考资料都是关于 .asp 页面的。

Application_Start

Application_StartApplication_End 方法是特殊方法,它们不代表 HttpApplication 事件。ASP.NET 为应用程序域的生命周期调用它们一次,而不是为每个 HttpApplication 实例调用。

此页面涉及 .aspx 页面。因此,您正在使用 MVC 并提到 global.asax,这就是您应该使用的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接