如何在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;
. NET实例化您的HttpApplication
派生类多次。我认为这是一个对象池。我觉得这个设计很可怕。它没有实际用途。
不要在应用程序对象中放置状态。创建一个具有静态变量的单独类。它们在每个AppDomain都是全局的。ASP。. NET不能乱动它们
当然,可能存在多个应用程序域同时运行的情况,但这种情况很少见。
在控制器上有以下覆盖:
protected override void OnActionExecuting(ActionExecutingContext filterContext)
protected override void OnActionExecuted(ActionExecutedContext filterContext)
我以前在一个baseController类中使用过这个。