Running the EndRequest_ application before the end of the request?

I have a few simple classes that should be removed at the end of the request.

To do this, I call the Dispose method for these 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 the Cannot access a disposed object. This happens in some MVC helpers.

It seemed to me that Application_EndRequest is launched at the end of the request. Is that not so? Is there another event that I should use to place my objects?

+4
source share
3 answers

Problems with the application pool - probably

I suspect that your one-time object is not associated with the request, but rather with a wide range of applications (it can be created for each request, but can use some common resources). While you are testing your application in a development environment, it seems to behave as expected, but as soon as you put it into production, you get problems. This means that you may have problems with the application pool .

The IIS web application pool capabilities actually create multiple HttpApplication instances for your application, and all of them can share one-time shared resources. If this is the case with your one-time object and you share it, it may be that it is not thread safe. The same can be said about the fact that you will not use shared access to resources in thread-safe operations.

So, it may happen that while one request is executed, another begins, and the first deletes the object while the second process still uses it.

Additional information is always helpful.

If you explain the nature of your one-time object / resource and how you use it in your application, we could help you much better. But at the same time, you can read my blog post , which talks about application pools and their processing. This does not apply to disposable items per se, but you can still find all the useful and useful information.

+5
source

If you need a one-time object for your internal controllers, I would recommend that you use controller lifecycle handlers instead of using Application_BeginRequest and Application_EndRequest. See the following example.

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

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; } } } 
+2
source

If the objects are tied to the controller level, you can override the Dispose Controller method to place these objects.

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

If you use some DI infrastructure (e.g. Ninject) in your application, you can delegate this work to it.

Instead of deleting objects at the end of a query, you can also try wrapping them in a using statement, wherever you go, this way you will ensure that the object is deleted.

0
source

Source: https://habr.com/ru/post/1438612/


All Articles