我已阅读John Thiriet上的博客文章,内容涉及“失火”方法。我确实实现了他的扩展方法,尽管使用它时会出错。
下面的示例代码:
public async Task<ActionResult> Index()
{
/*
a lot of work here
some sync services called, some awaits to async services
*/
// here I wanted to call logging service using "fire and forget",
// because I don't really care about it,
// and I don't need to wait for it to show the page for user
_logService.LogAsync(obj).FireAndForgetSafeAsync();
return RedirectToAction("Summary");
}
此博客文章中的方法如下:
public static class TaskUtilities
{
#pragma warning disable RECS0165 // Asynchronous methods should return a Task instead of void
public static async void FireAndForgetSafeAsync(this Task task, IErrorHandler handler = null)
#pragma warning restore RECS0165 // Asynchronous methods should return a Task instead of void
{
try
{
await task;
}
catch (Exception ex)
{
handler?.HandleError(ex);
}
}
}
并且代码使An asynchronous module or handler completed while an asynchronous operation was still pending
异常。我知道这是因为记录代码,但是我不确定为什么。当我尝试使用Index
在await LogAsync
内捕获时,它可以正常工作(也可以进行“慢速”调试)。如何处理此代码才能正常工作?我们可以使用其他方法来使这种扩展方法使控制器中的某些操作“失控”吗?有人可以向我解释什么是真正的错误以及为什么它不起作用吗? SImilar线程没有帮助我解释我的问题。谢谢。
答案 0 :(得分:1)
如果您的忘却日志记录代码使用了管道的任何上下文(例如,如果您正在记录调用者的查询字符串),则必须在HTTP请求完成之前的某个地方等待日志记录调用。否则,当ASP.NET拆除为请求创建的管道时,上下文可能会在记录之前消失。因此,ASP.NET会提示您该错误,以保护您免受自身伤害。
如果一劳永逸的日志记录代码未使用任何管道上下文(例如,它仅访问参数中提供给它的数据),则可以使用{{3} }。