ASP.NET Web API + 长时间运行的操作取消
Posted
技术标签:
【中文标题】ASP.NET Web API + 长时间运行的操作取消【英文标题】:ASP.NET Web API + Long running operation cancellation 【发布时间】:2012-04-03 11:34:37 【问题描述】:有没有办法在 ASP.NET Web API beta 中确定 HTTP 请求是否被取消(由于任何其他原因被用户中止)?我正在寻找机会拥有一种开箱即用的取消令牌,它会发出请求被中止的信号,因此也应该中止长时间运行的操作。
可能的相关问题 - CancellationTokenModelBinder 类的用例。为取消令牌设置单独的活页夹的原因是什么?
【问题讨论】:
【参考方案1】:您可以不时检查Response.IsClientConnected
,看看浏览器是否仍然连接到服务器。
【讨论】:
这似乎来自 ASP.NET MVC 堆栈,而不是来自 ASP.NET MVC Web API。如有错误请指正。 这是来自核心 ASP.Net 引擎。仅适用于 IIS 集成管道(不适用于 VS 调试模式)。 MSDN 涵盖了很好的文档:msdn.microsoft.com/en-us/library/… 感谢您的建议。这似乎是唯一的选择,我可能会在此基础上构建解决方案。【参考方案2】:我想总结一下。唯一可行的方法是检查 Response.IsClientConnected。 这里有一些关于舞台背后的技术细节: here 和 here 这种方法有一些缺陷:
仅在 IIS 下工作(无自托管,无开发服务器); 根据一些 SO 答案可能会很慢(在客户端断开连接后不要立即做出反应):here; 有关于此通话费用的注意事项:here最后我想出了以下代码,将基于 IsClientConnected 的 CancellationToken 注入 Web API 控制器:
public class ConnectionAbortTokenAttribute : System.Web.Http.Filters.ActionFilterAttribute
private readonly string _paramName;
private Timer _timer;
private CancellationTokenSource _tokenSource;
private CancellationToken _token;
public ConnectionAbortTokenAttribute(string paramName)
_paramName = paramName;
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
object value;
if (!actionContext.ActionArguments.TryGetValue(_paramName, out value))
// no args with defined name found
base.OnActionExecuting(actionContext);
return;
var context = HttpContext.Current;
if (context == null)
// consider the self-hosting case (?)
base.OnActionExecuting(actionContext);
return;
_tokenSource = new CancellationTokenSource();
_token = _tokenSource.Token;
// inject
actionContext.ActionArguments[_paramName] = _token;
// stop timer on client disconnect
_token.Register(() => _timer.Dispose());
_timer = new Timer
(
state =>
if (!context.Response.IsClientConnected)
_tokenSource.Cancel();
, null, 0, 1000 // check each second. Opts: make configurable; increase/decrease.
);
base.OnActionExecuting(actionContext);
/*
* Is this guaranteed to be called?
*
*
*/
public override void OnActionExecuted(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext)
if(_timer != null)
_timer.Dispose();
if(_tokenSource != null)
_tokenSource.Dispose();
base.OnActionExecuted(actionExecutedContext);
【讨论】:
还有一个使用 SignalR 和类似解决方案的选项,但它们对我来说有点超出了范围。【参考方案3】:如果你在控制器方法中添加了CancellationToken,它会被框架自动注入,当客户端调用xhr.abort()时,token会被自动取消
类似
public Task<string> Get(CancellationToken cancellationToken = default(CancellationToken))
对于MVC你也可以参考
HttpContext.Current.Response.IsClientConnected
HttpContext.Response.ClientDisconnectedToken
对于.NetCore
services.AddTransient<ICustomInterface>(provider =>
var accessor = provider.GetService<IHttpContextAccessor>);
accessor.HttpContext.RequestAborted;
);
【讨论】:
以上是关于ASP.NET Web API + 长时间运行的操作取消的主要内容,如果未能解决你的问题,请参考以下文章
部署在 IIS 上的 ASP.NET Core 对长时间运行的请求返回 502 错误
如何异步运行长时间运行的操作并在 ASP.Net Ajax 中为用户显示加载并轮询结果?
如何使用javascript在asp.net上停止正在进行的回发(长时间运行)?