Viv*_*vek 8 c# asp.net-web-api owin
我正在运行Owin Self托管的Web Api,其典型控制器如下:
[HttpGet]
[Route("refresh/{secId}")]
[ResponseType(typeof(int))]
public async Task<IHttpActionResult> RefreshElement(int secId)
{
var count = await _db.Refresh(secId);
if (count == 0)
return NotFound();
return Ok(count);
}
Run Code Online (Sandbox Code Playgroud)
假设_db.Refresh()长时间运行(几秒),有时会抛出异常.
我设法重现的问题是:
不再等待_db.Refresh的结果 - 因为我看到它何时返回异常,当任务是GCd时它会通过TPL未观察到的异常处理显示出来...
也许是因为这种互动,.net团队改变了未处理的异常政策而不是拆除流程(我认为是4.5以后)......那么这个问题的好处是什么?特别是对于使用OWIN的自托管WebApi - 因为我仍然将未观察到的异常记录为FATAL :)
我可以让_db.Refresh()接受一个取消令牌,但是我如何/何时在自我主机webapi中设置取消令牌以断开/取消?
Tim*_*lds 14
也许这并没有完全回答你的问题,但我相信它回答了最后一部分:
我可以让_db.Refresh()接受一个取消令牌,但是我如何/何时在自我主机webapi中设置取消令牌以断开/取消?
如果CancellationToken向操作方法添加参数,框架将在调用时提供一个参数.
[HttpGet]
[Route("refresh/{secId}")]
[ResponseType(typeof(int))]
public async Task<IHttpActionResult> RefreshElement(
int secId, CancellationToken cancellationToken)
{
var count = await _db.Refresh(secId, cancellationToken);
if (count == 0)
return NotFound();
return Ok(count);
}
Run Code Online (Sandbox Code Playgroud)
但请注意,在操作方法退出之前,客户端可能仍然存在一个小的机会窗口,在这种情况下,您的TPL未观察到的异常仍将发生.
您可以通过自己实现中间件来处理请求超时。
它IOwinContext有一个Request属性,它本身保存一个CancellationToken命名的属性CallCancelled,可以轮询该属性来查看请求是否被取消:
public class CancellationAwareOwinMiddleware : OwinMiddleware
{
public async Task Invoke(IOwinContext owinContext)
{
try
{
await Next.Invoke(owinContext);
}
catch (TaskCanceledException)
{
// Handle cancellation.
}
catch (Exception e)
{
if (owinContext.Request.CallCancelled.IsCancellationRequested)
{
// Handle cancellation.
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,存在一般异常子句,因为我不确定当 tge 请求被取消时,OWIN 是否会抛出 TCE,因此无论如何都要使用令牌来确定。
编辑:
正如 @usr 向我指出的那样,这个解决方案可以处理外部未被观察到的情况Task,这是我所做的一个相当大的假设。如果这是内部任务,我需要重新考虑解决方案。
| 归档时间: |
|
| 查看次数: |
8643 次 |
| 最近记录: |