在asp.net核心控制器中,为啥ExecutionContext.SuppressFlow()会抛出“AsyncFlowControl对象必须在创建它的线程上使用”。

Posted

技术标签:

【中文标题】在asp.net核心控制器中,为啥ExecutionContext.SuppressFlow()会抛出“AsyncFlowControl对象必须在创建它的线程上使用”。【英文标题】:In asp.net core controller, why does ExecutionContext.SuppressFlow() throw "AsyncFlowControl object must be used on the thread where it was created."在asp.net核心控制器中,为什么ExecutionContext.SuppressFlow()会抛出“AsyncFlowControl对象必须在创建它的线程上使用”。 【发布时间】:2019-06-17 00:04:34 【问题描述】:

我试图抑制跨异步线程的执行上下文流。我已经写了下面的代码,但它会引发错误 -

InvalidOperationException: AsyncFlowControl object must be used on the thread where it was created.
System.Threading.AsyncFlowControl.Undo()
Web1.Controllers.ValuesController+<Get>d__0.MoveNext() in ValuesController.cs
+
                throw;
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

当我通过代码进行调试时,not 会抛出错误。只有在我不调试时才会出现。

示例代码:

[HttpGet]
public async Task<IActionResult> Get()

    try
    
        using (ExecutionContext.SuppressFlow())
        
            await Switch.Instance.SwitchOn();
        
    
    catch (Exception ex)
    
        var x = ex.Message;
        throw;
    
    return Ok("Done!");

我是不是走错路了?

【问题讨论】:

执行使用await 设置的延续时,它可能位于与您的代码在await 之前所在的线程不同的线程上。 个人意见;不幸的是,这听起来像是 AsyncFlowControl 的一个非常糟糕的设计,因为它使用单词 Async 作为其名称的一部分并且不处理这种事情,听起来它更像是基于线程而不是异步(这是两个不同的东西)。 对我来说似乎很合理。一旦你在另一个线程上恢复,就为时已晚抑制执行上下文流。 【参考方案1】:

我正在尝试抑制跨异步线程的执行上下文流。

只需要问:为什么?

我已经写了下面的代码,但是它抛出了一个错误

当您在暂停它的不同线程上恢复执行上下文流时会发生此错误。

要修复此错误,请不要在 using 块中使用 await

Task task;
using (ExecutionContext.SuppressFlow())
  task = Switch.Instance.SwitchOn();
await task;

通过使using 中的代码保持同步,您可以确保保持在同一个线程上。

【讨论】:

以上是关于在asp.net核心控制器中,为啥ExecutionContext.SuppressFlow()会抛出“AsyncFlowControl对象必须在创建它的线程上使用”。的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Asp.Net Core Kestrel 服务器向 Ngrok 返回 404 并且控制器永远不会被调用?

为啥图像不显示在我的 ASP.Net 核心网站上?

为啥此代码给我来自 Request.Form 的无效内容类型? (ASP.NET 核心)

为啥 Asp.net web api 控制器不从 IController 派生

如何在 asp.net 核心 webapi 控制器中读取请求正文?

如何在 asp.net 核心中正确格式化堆栈跟踪信息