如何在Application_BeginRequest中执行第一个到达web服务器的请求的一部分代码

本文关键字:服务器 web 请求 代码 一部分 第一个 Application BeginRequest 执行 | 更新日期: 2023-09-27 18:06:42

我想记录到达服务器的第一个请求,所以我在Global.asax.cs中编写了这部分代码

private bool _startupHasBeenLogged = false;
protected void Application_BeginRequest(object sender, EventArgs e)
{
    if (!_startupHasBeenLogged)
    {
        DoLog();
        _startupHasBeenLogged = true;
    }
}

问题是我得到了前5或6个请求的日志。我猜服务器一次接收多个请求,所以DoLog在布尔值变为真之前会多次点击。

我试过使用Interlocked:

int running = 0;
protected void Application_BeginRequest(object sender, EventArgs e)
{
    if (Interlocked.CompareExchange(ref running, 1, 0) != 0) return;
    if (!_startupHasBeenLogged)
    {
        _startupHasBeenLogged = true;
        DoLog();
    }
    Interlocked.Exchange(ref running, 0);
}

和监控。TryEnter:

private static readonly object _lock = new object();
protected void Application_BeginRequest(object sender, EventArgs e)
{
    if (Monitor.TryEnter(_lock))
    {
        try
        {
            if (!_startupHasBeenLogged)
            {
                _startupHasBeenLogged = true;
                DoLog();
            }
        }
        finally
        {
            Monitor.Exit(_lock);
        }
    }
}

但是每次,日志都会触发5或6次。

那么我如何运行一个代码只有一次在一个web服务器的第一个请求?

编辑方案:

我错过的细节是应用程序被实例化多次,所以_startupHasBeenLogged有多个实例。这把锁很好用。只需声明一个静态bool

private static bool _startupHasBeenLogged = false;

如何在Application_BeginRequest中执行第一个到达web服务器的请求的一部分代码

. NET实例化您的HttpApplication派生类多次。我认为这是一个对象池。我觉得这个设计很可怕。它没有实际用途。

不要在应用程序对象中放置状态。创建一个具有静态变量的单独类。它们在每个AppDomain都是全局的。ASP。. NET不能乱动它们

当然,可能存在多个应用程序域同时运行的情况,但这种情况很少见。

在控制器上有以下覆盖:

protected override void OnActionExecuting(ActionExecutingContext filterContext)

protected override void OnActionExecuted(ActionExecutedContext filterContext)

我以前在一个baseController类中使用过这个。

相关文章: