HttpApplication does not quit

2019-05-10 07:48发布

I have a single page app with Angular.js front, web api2 back end, also using Castle Windsor and SignalR.

I am using a c# component on the server that maintains server state. So, on Application_Start() I register the main component with Castle Windsor as Singleton.

IoC.Container.Register(Component.For(typeof(MainManager)).ImplementedBy(typeof(MainManager)).LifeStyle.Singleton);

(however, I tested PerWebRequest and few other lifestyles, but the main problem remains the same, the started task does not quit)

Then in my Web Api, I can execute commands against that instance.

[HttpGet]
public void StartProcess(Params p) {
  IoC.Resolve<MainManager>().StartOperation(p);
}

and this also gives me opportunity to stop it from the website by calling another controller method

[HttpGet]
public void Stop() {
  IoC.Resolve<MainManager>().RequestStop();
}

This works great for the most part. However, sometimes my application gets in a bad state (for a multitude of reasons, It can get restarted in prod) I can emulate this problem by modifying web.config during running the operation, so a lot of things reset (such as Signal-R connection), but the main operation does not stop running.

(In fact, once my application is in bad state I can no longer call that Stop controller method because MainManager has been reset, so the only way to stop it as of now is to reset the whole IIS. This is certainly not desired)

I am trying to figure out how to detect this state, and terminate the running process.

As one possible solution, I am experimenting with using Bound lifestyle (new in Castle Windsor 3), trying to scope my manager to my web api httpapplication, but no luck yet.

update

I tried making the main task method static

[HttpGet]
public void Start(ForceData data) {
  MainManager.Start(data);
}

I believe this should take out the singleton instance out of equation, but the code still runs un-interrupted after touching web.config

update

took the MainManager class out of equation. All my web api method does now is loop + sleep

[HttpGet]
public void Start(ForceData data) {
  foreach (var e in data.Members)
  {
    _log.Info("processing member: {0}", e.Email);
    Thread.Sleep(1000);
  }
}

this loop is also not interrupted after touching web.config.

So, at this point I am reading about MVC request lifecycle to figure out at which point this request goes zombie rouge

1条回答
Viruses.
2楼-- · 2019-05-10 08:41

This is by design, as HttpApplication instances are not freed immediately when application restarts,

http://msdn.microsoft.com/en-us/library/vstudio/ms178473%28v=vs.100%29.aspx

When an application restart is required, ASP.NET will serve all pending requests from the existing application domain and the old assemblies before restarting the application domain and loading the new assemblies.

In all your sample Web API method, you can see the thread is still busy, which means ASP.NET runtime considers this request is still being processed.

查看更多
登录 后发表回答