在等待时使用任务扩展方法时,异步操作仍处于挂起状态

时间:2019-01-11 18:28:03

标签: asp.net .net asynchronous model-view-controller async-await

我已阅读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异常。我知道这是因为记录代码,但是我不确定为什么。当我尝试使用Indexawait LogAsync内捕获时,它可以正常工作(也可以进行“慢速”调试)。如何处理此代码才能正常工作?我们可以使用其他方法来使这种扩展方法使控制器中的某些操作“失控”吗?有人可以向我解释什么是真正的错误以及为什么它不起作用吗? SImilar线程没有帮助我解释我的问题。谢谢。

1 个答案:

答案 0 :(得分:1)

如果您的忘却日志记录代码使用了管道的任何上下文(例如,如果您正在记录调用者的查询字符串),则必须在HTTP请求完成之前的某个地方等待日志记录调用。否则,当ASP.NET拆除为请求创建的管道时,上下文可能会在记录之前消失。因此,ASP.NET会提示您该错误,以保护您免受自身伤害。

如果一劳永逸的日志记录代码未使用任何管道上下文(例如,它仅访问参数中提供给它的数据),则可以使用{{3} }。

另请参阅QueueBackgroundWorkItem