【问题标题】:Asynchronous operation was still pending when using task extension method with await使用带有 await 的任务扩展方法时,异步操作仍处于挂起状态
【发布时间】:2019-01-12 08:09:55
【问题描述】:

我已经阅读了来自 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 中尝试捕获时,它工作正常(也可以进行“慢”调试)。如何处理此代码以正常工作?我们可以使用等待其他方法在控制器中制作这样的扩展方法以使某些操作“一劳永逸”吗?有人可以向我解释什么是真正的错误以及为什么它不起作用?类似的线程并没有帮助我解释我的问题。谢谢。

【问题讨论】:

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


【解决方案1】:

如果您的“一劳永逸”日志代码使用管道的任何上下文(例如,如果您正在记录调用者的查询字符串),您必须在 HTTP 请求完成之前在某处等待日志调用。否则,当 ASP.NET 拆除它为请求创建的管道时,上下文可能会在它被记录之前消失。这就是 ASP.NET 为您提供该错误的原因,以保护您免受自己的伤害。

如果您的“一劳永逸”日志代码不使用任何管道上下文(例如,它只访问在参数中提供给它的数据),那么您可以使用QueueBackgroundWorkItem 允许它在管道完成后运行。

另见this answer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-30
    • 2013-03-08
    相关资源
    最近更新 更多