请求结束前触发Application_EndRequest?

时间:2012-10-09 09:59:55

标签: asp.net asp.net-mvc asp.net-mvc-3

我有一些简单的类需要在请求结束时处理。

为此,我在Dispose中的Application_EndRequest事件中对这些对象调用Global.asax方法。

这“在我的机器上工作正常”但在我的生产服务器上导致一些问题Cannot access a disposed object.这种情况发生在一些MVC助手中。

在我看来,Application_EndRequest在请求结束时被触发。这不是这种情况吗?我应该用另一个事件处理我的物品吗?

3 个答案:

答案 0 :(得分:5)

应用程序池问题 - 可能

我怀疑你的一次性对象没有绑定请求,而是app wide(它可以根据请求进行实例化,但可能使用了一些共享资源)。只要您在开发环境中测试应用程序,它似乎就像预期的那样行事,但只要您将其投入生产就会出现问题。 这表示您可能遇到应用程序池问题

IIS Web应用程序池功能实际上为您的应用程序实例化多个HttpApplication实例,并且它们可能共享公共可用资源。如果您的一次性物品就是这种情况并且您正在共享它,则可能是它不是线程安全的。如果不将共享资源使用包装在线程安全操作中,情况也是如此。

这就是为什么当一个请求正在进行时,另一个请求开始,第一个处理该对象,而第二个进程仍在使用它时,可能会发生这种情况。

更多信息总是有帮助的

如果您要解释一次性物品/资源的性质以及您在应用程序中如何使用它,我们可以更好地帮助您。但与此同时,您可以 read my blog post 讨论应用程序池并处理它们。这不是关于一次性物品本身,但您仍然可以发现所有信息都非常有用和有用。

答案 1 :(得分:2)

如果您需要在控制器内部使用某个对象一次性请求,我建议您使用控制器的生命周期处理程序,而不是使用Application_BeginRequest和Application_EndRequest。请参阅以下示例。

控制器:

public class BaseController : Controller
{
    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);

        this.HttpContext.Items["MyDisposableObject"] = new MyDisposableObject();
    }

    protected override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        base.OnResultExecuted(filterContext);

        if (this.HttpContext.Items.Contains("MyDisposableObject"))
        {
            var myDisposableObject = 
                    this.HttpContext.Items["MyDisposableObject"] as IDisposable;

            if (myDisposableObject != null)
            {
                myDisposableObject.Dispose();
            }
        }
    }
}

IDisposable对象:

public sealed class MyDisposableObject : IDisposable
{
    private bool disposed;

    public void Dispose()
    {
        if (!this.disposed)
        {
            // Dispose all managed 
            // and unmanaged resources. 

            // Note disposing has been done.
            this.disposed = true;
        }
    }
}

答案 2 :(得分:0)

如果对象的范围限定为控制器级别,则可以覆盖Dispose Controller方法来处置这些对象。

protected override void Dispose(bool disposing)
{
  if(disposing)
  {
    // dispose the objects here
  }

  base.Dispose(disposing);
}

如果您在应用程序中使用某些DI框架(如Ninject),则可以将该作业委派给他们。

除了在请求的末尾处理对象,您还可以尝试将它们包装在using语句中,只要您通过这种方式访问​​它,就可以确保对象处理完毕。