STA MVC 应用程序不会结束长 运行 请求
STA MVC application doesnt end long running requests
我需要 运行 我的 ASP.NET MVC 应用程序处于 STA 模式。为此,我在 Programming ASP.NET MVC 4: Developing Real-World Web Applications with ASP.NET MVC 的基础上开发了一些自定义的 类。他们在这里:
public class StaThreadRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
if (requestContext == null)
throw new ArgumentNullException("requestContext");
return new StaThreadHttpAsyncHandler(requestContext);
}
}
public class StaThreadHttpAsyncHandler : Page, IHttpAsyncHandler, IRequiresSessionState
{
private readonly RequestContext _requestContext;
public StaThreadHttpAsyncHandler(RequestContext requestContext)
{
if (requestContext == null)
throw new ArgumentNullException("requestContext");
_requestContext = requestContext;
}
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
return this.AspCompatBeginProcessRequest(context, cb, extraData);
}
protected override void OnInit(EventArgs e)
{
var controllerName = _requestContext.RouteData.GetRequiredString("controller");
var controllerFactory = ControllerBuilder.Current.GetControllerFactory();
var controller = controllerFactory.CreateController(_requestContext, controllerName);
if (controller == null)
throw new InvalidOperationException("Could not find controller: " + controllerName);
try
{
controller.Execute(_requestContext);
}
finally
{
controllerFactory.ReleaseController(controller);
}
this.Context.ApplicationInstance.CompleteRequest();
}
public void EndProcessRequest(IAsyncResult result)
{
this.AspCompatEndProcessRequest(result);
}
public override void ProcessRequest(HttpContext httpContext)
{
throw new NotSupportedException("STAThreadRouteHandler does not support ProcessRequest called (only BeginProcessRequest)");
}
}
同时调整了RouteConfig:
routes.Add(new Route("{controller}/{action}/{id}", new StaThreadRouteHandler ()))
对于我的大部分操作,一切正常,但我有两个需要 10 到 20 秒才能完成。对于这两个操作,方法 EndProcessRequest
永远不会执行,即使在执行期间没有抛出异常并且 this.Context.ApplicationInstance.CompleteRequest();
在 OnInit
中被调用也没有问题。因此,此类请求在 IIS 中以状态 ExecuteRequestHandler
结束,并永远停留在那里,并且还会阻止新请求得到服务。
为什么会这样?为什么 EndProcessRequest
中的断点在长时间的 运行ning 操作中永远不会命中,而对于较短的操作(1-5 秒)却可以正常工作。
问题与特定操作的执行时间完全无关。不太确定幕后发生了什么,但所有有问题的操作都有一个共同点——它们正在创建一个特定的 COM 对象,我猜它在某种程度上没有被正确销毁,因此 EndProcessRequest
没有被调用。
任何 .NET COM 对象都会出现此问题,本机 COM 对象正常并且 EndProcessRequest
被调用。
我需要 运行 我的 ASP.NET MVC 应用程序处于 STA 模式。为此,我在 Programming ASP.NET MVC 4: Developing Real-World Web Applications with ASP.NET MVC 的基础上开发了一些自定义的 类。他们在这里:
public class StaThreadRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
if (requestContext == null)
throw new ArgumentNullException("requestContext");
return new StaThreadHttpAsyncHandler(requestContext);
}
}
public class StaThreadHttpAsyncHandler : Page, IHttpAsyncHandler, IRequiresSessionState
{
private readonly RequestContext _requestContext;
public StaThreadHttpAsyncHandler(RequestContext requestContext)
{
if (requestContext == null)
throw new ArgumentNullException("requestContext");
_requestContext = requestContext;
}
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
return this.AspCompatBeginProcessRequest(context, cb, extraData);
}
protected override void OnInit(EventArgs e)
{
var controllerName = _requestContext.RouteData.GetRequiredString("controller");
var controllerFactory = ControllerBuilder.Current.GetControllerFactory();
var controller = controllerFactory.CreateController(_requestContext, controllerName);
if (controller == null)
throw new InvalidOperationException("Could not find controller: " + controllerName);
try
{
controller.Execute(_requestContext);
}
finally
{
controllerFactory.ReleaseController(controller);
}
this.Context.ApplicationInstance.CompleteRequest();
}
public void EndProcessRequest(IAsyncResult result)
{
this.AspCompatEndProcessRequest(result);
}
public override void ProcessRequest(HttpContext httpContext)
{
throw new NotSupportedException("STAThreadRouteHandler does not support ProcessRequest called (only BeginProcessRequest)");
}
}
同时调整了RouteConfig:
routes.Add(new Route("{controller}/{action}/{id}", new StaThreadRouteHandler ()))
对于我的大部分操作,一切正常,但我有两个需要 10 到 20 秒才能完成。对于这两个操作,方法 EndProcessRequest
永远不会执行,即使在执行期间没有抛出异常并且 this.Context.ApplicationInstance.CompleteRequest();
在 OnInit
中被调用也没有问题。因此,此类请求在 IIS 中以状态 ExecuteRequestHandler
结束,并永远停留在那里,并且还会阻止新请求得到服务。
为什么会这样?为什么 EndProcessRequest
中的断点在长时间的 运行ning 操作中永远不会命中,而对于较短的操作(1-5 秒)却可以正常工作。
问题与特定操作的执行时间完全无关。不太确定幕后发生了什么,但所有有问题的操作都有一个共同点——它们正在创建一个特定的 COM 对象,我猜它在某种程度上没有被正确销毁,因此 EndProcessRequest
没有被调用。
任何 .NET COM 对象都会出现此问题,本机 COM 对象正常并且 EndProcessRequest
被调用。