You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Framework 4.8 ASP.NET中Async/Await线程阻塞问题排查求助

ASP.NET .NET Framework 4.8 异步死锁问题排查与临时解决

问题现象

在ASP.NET .NET Framework 4.8中遇到特殊死锁问题:通过反射加载类后调用同步方法,该方法内部使用.Wait()或.GetAwaiter().GetResult()调用异步方法;若异步方法中的await未添加.ConfigureAwait(false),会出现调用永不返回、线程阻塞的情况,原应用甚至会导致IIS挂起(一段时间后因应用池回收恢复)。注:复现示例中IIS仍能接受新请求,但调用本身会一直阻塞。

此问题仅出现在ASP.NET .NET Framework 4.8环境,相同代码在.NET Framework 4.8的Windows服务、.NET 8中运行正常(DLL为多目标框架)。

临时解决方案

  • 将页面改为全异步模式,从上到下改造代码→不可行,属于遗留单体应用,改造成本极高
  • 为所有异步调用添加.ConfigureAwait(false)→不可行,大量代码由自研ORM工具自动生成,修改成本过高
  • 将涉及方法改为同步实现,移除所有异步调用→已采用此方案,虽不满意但影响范围小,改动成本低

问题推测与困惑

查阅资料后推测,可能是ASP.NET自定义的System.Web.AspNetSynchronizationContext导致回调异常,但因程序挂起无法验证,对此深感困惑。

补充:调试需求与本质疑问

真正想搞清楚的是:

  1. 如何调试这类编译器生成状态机的场景,定位线程恢复失败的原因
  2. 此问题的本质原因是什么

复现代码

页面调用代码

protected void Page_Load(object sender, EventArgs e)
{
    string Lstr_PathDLL = "full path to DLL";
    Assembly Lobj_Assembly = Assembly.LoadFile(Lstr_PathDLL);
    IAwaitErrorNetFrameworkASPNET Lobj_Error = (IAwaitErrorNetFrameworkASPNET)Lobj_Assembly.CreateInstance("LoadedByReflection.AwaitErrorNetFrameworkASPNET");
    Lobj_Error.Test();
}

组件类代码

using Dominio;
using System.Threading.Tasks;

namespace LoadedByReflection
{
    public class AwaitErrorNetFrameworkASPNET : IAwaitErrorNetFrameworkASPNET
    {
        public void Test()
        {
            Teste2().GetAwaiter().GetResult();
        }

        private async Task Teste2()
        {
            await Task.Delay(1000);
        }
    }
}

后续反馈

正如@Charlieface和Srinivasan Jayakumar所指出,创建新线程调用代码可解决问题,但这并非最佳实践,而老旧遗留系统难以遵循最佳实践。目前问题已解决,但仍无法调试System.Web.AspNetSynchronizationContext,也不清楚为何死锁仅出现在ASP.NET而非Windows服务中,感谢各位帮助。


内容的提问来源于stack exchange,提问作者Ângelo Cossa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 11:06:24