【问题标题】:Difference between Application_Start and Application_OnStartApplication_Start 和 Application_OnStart 之间的区别
【发布时间】:2011-01-04 17:49:35
【问题描述】:

我正在将 ASP.NET MVC 代码添加到预先存在的 ASP.NET Webforms 项目中。 various tutorials 建议将路由添加到从 Global.asax 中的 Application_Start() 调用的方法中。我的 Global.asax 已经有一个 Application_OnStart(Object,EventArgs) 方法和一些设置代码。

如果我尝试同时使用 Start 和 OnStart,则不会调用 OnStart(并且设置失败,从而导致错误)。看来我必须选择其中一个。

我的问题是:我应该使用哪一个?它们之间有什么区别?他们是否在不同的时间被调用?

(注意:在撰写本文时,top three Google 命中是无用和/或误导的。我希望 Stack Overflow 可以解决这个问题。)

【问题讨论】:

    标签: asp.net asp.net-mvc global-asax


    【解决方案1】:

    在经典(旧版)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)");
        }
    }
    

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

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

    【讨论】:

    • 很好的解释,尤其是不同的方法签名。
    • 我对这个解释有疑问。当您说“在处理任何 .ASP 文件之前运行一次”时,这是否意味着该进程在服务器启动时或在每个 HTTP 连接开始时运行?如果是前者,那么是否有可能实例化一个可以运行应该贯穿应用程序生命周期的后台进程的单例?
    • @miken.mkndev 应用程序在收到 HTTP 请求之前不会这样做。当此请求到达时,IIS 将启动应用程序进程,运行任何 Application_Start 事件,然后处理传入的请求。部署脚本通常会部署新版本的应用程序,然后发出 HTTP 请求以立即启动应用程序 - 特别是如果 Application_Start 需要几秒钟才能完成。最好提前做到这一点,而不是惩罚在部署后碰巧成为您的第一个访问者的不幸用户。
    • @miken.mkndev 至于后台进程 - 可能,但真的不推荐。查看haacked.com/archive/2011/10/16/…hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx,了解有关如何将后台任务作为 ASP.NET 应用程序的一部分运行的更多讨论。
    【解决方案2】:

    根据Microsoft docs on the ASP.Net app life cycle,您应该在 global.asax 文件中使用 Application_start 方法:

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

    Application_OnStart:Application_OnStart 事件发生在第一个新会话创建之前(第一次引用 Application 对象时)。 This goes in Global.asa,不是 global.asax。

    【讨论】:

    • 我猜 OnStart 在 ASP.NET/Global.asax 中工作,就像与旧版 ASP 的向后兼容移动一样。到目前为止,我已将我的应用程序翻转为 Start 并且没有任何不良影响。谢谢!
    【解决方案3】:

    Application_OnStart:

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

    我能找到的所有参考资料都指向 .asp 页面

    Application_Start

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

    此页面指的是 .aspx 页面。因此,当您使用 MVC 并提及 global.asax 时,这是您应该使用的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-25
      • 2020-05-10
      • 2014-09-20
      • 2010-10-28
      • 2015-10-04
      • 2012-08-12
      • 2011-02-18
      • 2019-12-21
      相关资源
      最近更新 更多