linkerro
linkerro

Reputation: 5458

Application_EndRequest triggered before request end?

I have some simple classes that need to be disposed a the end of the request.

For that end I call the Dispose method on those objects from the Application_EndRequest event in Global.asax.

This "works fine on my machine" but causes some problems on my production server where I get Cannot access a disposed object. This happens in some MVC helpers.

It seemed to me like Application_EndRequest is triggered at the end of the request. Is this not the case? Is there another event I should be using to dispose my objects?

Upvotes: 4

Views: 3814

Answers (3)

Robert Koritnik
Robert Koritnik

Reputation: 104999

Application pool issues - likely

I suspect that your disposable object isn't bound to request but rather app wide (it may be instantiated per request but it may be using some shared resources). As long as you're testing your application in development environment it seems to behave as expected but as soon as you put it in production you get issues. This indicates you may have problems with application pool.

IIS web application pool capabilities actually instantiate several HttpApplication instances for your application and they may all share common disposable resources. If that's the case with your disposable object and you're sharing it it may be that it isn't thread safe. The same would be true when you wouldn't wrap your shared resource usage inside thread safe operations.

That's why it may happen that while one request is in progress another one begins and the first one disposed the object while the second process still uses it.

More information is always helpful

If you'd explain the nature of your disposable object/resource and how you're using it in your application we could help you much better. But in the meantime, you could read my blog post that talks about application pools and handling them. It's not about disposable objects per se, but you may still find all the information very useful and helpful.

Upvotes: 5

VJAI
VJAI

Reputation: 32758

If the objects are scoped to controller level you can override the Dispose method of Controller to dispose those objects.

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

  base.Dispose(disposing);
}

If you are using some DI framework (like Ninject) in your application you can delegate that job to them.

Instead of disposing the objects at the end of the request you can also try wrapping them in an using statement wherever you access by this way you make sure the object is disposed.

Upvotes: 0

Dmitrii
Dmitrii

Reputation: 1257

If you need some object disposable per-request to use inside your controllers, I would recommend you using controller's lifecycle handlers instead of using Application_BeginRequest and Application_EndRequest. See the following example.

The Controller:

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();
            }
        }
    }
}

The IDisposable object:

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;
        }
    }
}

Upvotes: 2

Related Questions