关于Application_End 与 Application_Start事件触发情况的测试(待续)

测试项目搭建

定义一个简单的Mvc项目,有如下文件:

(1)

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Run(context =>
        {
            return Task.Run(
                async () => {
                    await Task.Delay(600);
                    await context.Response.WriteAsync("Hello, world." + context.Request.Uri);
                });
        });
    }
}

(2)

public class Global : System.Web.HttpApplication
{
    protected void Application_Start(object sender, EventArgs e)
    {
        DebugUtils.Log("Application_Start");

        Task.Run(() => { DebugUtils.beginLog($"bugLog.txt"); });

        for (long i = 0; i < 10000000000; i++) ;

        DebugUtils.Log("Application_Start finished");
    }

    protected void Application_End(object sender, EventArgs e)
    {
        DebugUtils.Log("Application_End");

        for (long i = 0; i < 10000000000; i++) ;

        DebugUtils.Log("Application_End finished");
    }
}

(3)

public class DebugUtils
{

    public static ConcurrentQueue<string> queue = new ConcurrentQueue<string>();

    public static void beginLog(string fileName)
    {
        string dirPath = "G:\\c#\\www\\debugLog\\";
        if (!Directory.Exists(dirPath))
            Directory.CreateDirectory(dirPath);

        using (FileStream fs = new FileStream(dirPath + "/" + fileName, FileMode.Append))
        {
            using (StreamWriter sw = new StreamWriter(fs))
            {
                string str;
                while (true)
                {
                    if (queue.TryDequeue(out str))
                    {
                        sw.WriteLine(str);
                        sw.Flush();
                    }
                }

            }
        }
    }

    public static void Log(string str)
    {
        queue.Enqueue("[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff") + "]--[" + Thread.CurrentThread.ManagedThreadId + "]--" + str);
    }
}

测试

常规操作

将站点部署到IIS上后,依次进行 修改config, bin文件夹,站点关闭、重启,回收线程池 操作,日志里都有Application_End的触发日志。随后访问页面又会有Application_Start的日志记录。

高并发

使用工具模拟请求高并发地访问这个站点

在此期间修改config, 日志文件中只有Application_End的记录,却没有Application_Start的记录。
再次修改config,这次只有Application_Start的记录,却又没有end的了。尝试多次,一直都这样轮替出现。

虽然上面日志中的记录看上去很平常,但是实际情况却不是这样。



于是做了如下修改(每次启动都使用新的日志文件)

同样进行了几次config文件的修改,新的日志记录如下

可以看到Application_Start事件并不会等待Application_End执行完毕才触发。

待解决的疑问:

  1. 上面测试中情况
    前面使用同一个日志文件时,日志只记录部分,是因为文件被占用吗,那为什么会没有异常。
    很规律地交替出现又是什么情况……
  2. 项目中遇到的问题

项目中使用log4net记录日志 ,配置文件如下:

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender" >
    <file value="App_Data/Logs/Logs.txt" />
    <encoding value="utf-8" />
    <appendToFile value="true" />
    <rollingStyle value="Size" />
    <maxSizeRollBackups value="10" />
    <maximumFileSize value="10000KB" />
    <staticLogFileName value="true" />
    <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" />
    </layout>
</appender>
<root>
    <appender-ref ref="RollingFileAppender" />
    <level value="DEBUG" />
</root>
</log4net>

Application_Start:

    protected override void Application_Start(object sender, EventArgs e)
    {
        Clock.Provider = ClockProviders.Utc;

        //Log4Net configuration
        AbpBootstrapper.IocManager.IocContainer
            .AddFacility<LoggingFacility>(f => f.UseAbpLog4Net()
                .WithConfig(Server.MapPath("log4net.config"))
            );

        base.Application_Start(sender, e);

        SingletonDependency<IOnlineUserManager>.Instance.ReloadWhenApplicationStart();
    }

在站点发布后,常常会在某次Application_End事件触发后,日志不再记录,而等过段时间后又会有新的日志出现(Application_Start的日志为起始)。

如果Application_End事件触发后,随之一定会触发Application_Start,那 SingletonDependency.Instance.ReloadWhenApplicationStart();这行代码为什么经常不生效。

是否像上面的测试中情况那样,出现了执行次序的问题,先触发了Application_Start,而后触发Application_End,导致读取缓存的session信息时,相应文件还没有保存。

修改日志记录文件

public class DebugUtils
{
    public static DebugUtils Instance = new DebugUtils();

    public static ConcurrentQueue<string> queue = new ConcurrentQueue<string>();

    public  void beginLog(string fileName)
    {
        string dirPath = "G:\\c#\\www\\debugLog\\";
        if (!Directory.Exists(dirPath))
            Directory.CreateDirectory(dirPath);

        using (FileStream fs = new FileStream(dirPath + "/" + fileName, FileMode.Append))
        {
            using (StreamWriter sw = new StreamWriter(fs))
            {
                string str;
                while (true)
                {
                    if (queue.TryDequeue(out str))
                    {
                        sw.WriteLine(str);
                        sw.Flush();
                    }
                }

            }
        }
    }

    public  void Log(string str, string date)
    {
        queue.Enqueue($"[{ date }]--[{Thread.CurrentThread.ManagedThreadId}]-[{ this.GetHashCode() }]-{str}");
    }
}

public class Global : System.Web.HttpApplication
{
    protected void Application_Start(object sender, EventArgs e)
    {
        DebugUtils.Instance.Log("Application_Start", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"));

        Task.Run(() => { DebugUtils.Instance.beginLog($"bugLog{DateTime.Now.ToString("yyyyMMdd-HHmmssfff")}.txt"); });

        for (long i = 0; i < 10000000000; i++) ;

        DebugUtils.Instance.Log("Application_Start finished", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"));
    }

    protected void Application_End(object sender, EventArgs e)
    {
        DebugUtils.Instance.Log("Application_End", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"));

        for (long i = 0; i < 10000000000; i++) ;

        DebugUtils.Instance.Log("Application_End finished", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"));
    }
}

原文地址:https://www.cnblogs.com/wj033/p/8970691.html

时间: 2024-10-10 21:22:35

关于Application_End 与 Application_Start事件触发情况的测试(待续)的相关文章

Android Activity 和 ViewGroup中事件触发和传递机制

1.在只有Activity的情况: 1)Touch事件触发流程: 首先触发dispatchTouchEvent 然后触发onUserInteraction 再次onTouchEvent 如果是点击的话,紧跟着下列事件(点击分俩步,ACTION_DOWN,ACTION_up) 触发dispatchTouchEvent 再次onTouchEvent 当ACTION_up事件时不会触发onUserInteraction(可查看源代码) 2)键盘事件触发流程 首先触发dispatchKeyEvent 然

Zendframework 模块加载事件触发顺序。

模块加载时事件触发的时间顺序: 1.  loadModule.resolve(ModuleEvent::EVENT_LOAD_MODULE_RESOLVE):模块将被加载时触发,事件监听者将模块名解析成类的实例.监听者使用getModuleName()获取模块名. 2.  loadModule(ModuleEvent::EVENT_LOAD_MODULE):一旦模块被解析成对象后,本事件会被触发,与之相对的事件监听者会加载模块(将新建的对象传递给所有的监听者). 3.  mergeConfig(

Javascript事件触发顺序

html标签是有子和父的,这个时候就出现了事件触发顺序的问题,比如: <!DOCTYPE html> <html> <head> <style> .first{ border:solid #FF0000 } .second{ border:solid #00FF00 } .third{ border:solid #0000FF } </style> <script src="http://libs.baidu.com/jquery

input 输入框的事件触发及其顺序

代码:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <input id="field" type="text" /> <br/> <input type=&quo

[转载] 理解 epoll 的事件触发机制

原文: http://weibo.com/p/1001603862394207076573?sudaref=weibo.com epoll的I/O事件触发方式有两种模式:ET(Edge Triggered)和LT(Level Triggered). 这个触发模式其实是events(事件)的属性,该属性是和POLLIN.POLLOUT等属性并列且混杂使用的,而events有时依附在fd(文件描述符)上的,所以可以说:这个触发模式是events所依附的fd的属性.区分events和fd的原因是ker

解决jQuery中dbclick事件触发两次click事件

首先感谢这位小哥!http://qubernet.blog.163.com/blog/static/1779472842011101505853216/ 太长姿势了. 在jQuery事件绑定中,dbclick可以触发两次click事件.例如一个DOM元素div,既绑定了 click 事件,又绑定了 dblclick 事件,这两个事件分别要做独立的事情.事件处理上没有冲突,都可以各自完成各自的操作.双击的时候虽然是执行了 dblclick 事件,但是在这之前,也执行了click 事件,那么,如何来

网络事件触发自己主动登录

通过接收REACHABILITY_RECOVE_NOTIFICATION通知来获取网络状态.可是在弱网络下可能出现收不到通知的情况,iphone 4s有时候也出现收不到网络通知的情况.其他90%以上的情况都能收到网络通知. 登录时能够依据该通知来触发自己主动登录.防止没有收到网络通知就登录,导致登录失败,不能显示正常网络提示:也避免了起定时器等待一段时间在登录的不及时及耗电量问题(起线程非常费电). 而且用停止网络检查立马启动网络检查会出现.收到两次网络正常通知(若网络正常的情况下) :[g_r

网络事件触发自动登录

通过接收REACHABILITY_RECOVE_NOTIFICATION通知来获取网络状态,但是在弱网络下可能出现收不到通知的情况,iphone 4s有时候也出现收不到网络通知的情况,其它90%以上的情况都能收到网络通知. 登录时可以根据该通知来触发自动登录,防止没有收到网络通知就登录,导致登录失败,不能显示正常网络提示:也避免了起定时器等待一段时间在登录的不及时及耗电量问题(起线程很费电).并且用停止网络检查立刻启动网络检查会出现,收到两次网络正常通知(若网络正常的情况下) :[g_reach

【阿里云IoT+YF3300】4.Alink物模型之事件触发

名词解释:设备的功能模型之一,设备运行时的事件,事件一般包含需要被外部感知和处理的通知信息,可包含多个输出参数.如,某项任务完成的信息,或者设备发生故障或告警时的温度等,事件可以被订阅和推送. 在工控领域,通信的实时性非常重要,所以有所谓的工业以太网(时间敏感网络TSN).5G之所以成为未来物联网的基石,也是因为时延非常低(毫秒级),才能使无人驾驶落地成为可能. 不过在一些典型的物联网领域,其上传数据的频率却没有那么快,比如环境的温湿度,一般都是分钟级别上传.这就带来一个问题,如果上传的间隔比较