ASP.NET MVC项目部署到IIS后,w3wp.exe程序报错重启

时间:2025-03-02 11:34:20

一、错误信息

windows的事件查看器》windows日志》应用程序,按时间找到错误信息如下:

错误应用程序名称: w3wp.exe,版本: 10.0.14393.0,时间戳: 0x57899b8a
错误模块名称: KERNELBASE.dll,版本: 10.0.14393.5850,时间戳: 0x64253b4c
异常代码: 0xe0434352
错误偏移量: 0x0000000000026ea8
错误进程 ID: 0x16e4
错误应用程序启动时间: 0x01db8a5e79c7e198
错误应用程序路径: c:\windows\system32\inetsrv\w3wp.exe
错误模块路径: C:\Windows\System32\KERNELBASE.dll
报告 ID: b09d1188-9098-4134-982d-7785f7fa3cc4
错误程序包全名: 
错误程序包相对应用程序 ID: 

二、错误分析

DeepSeek给出的报错分析:

1. 错误信息解析

  • 异常代码0xE0434352 → ​CLR 异常,表示托管代码中未处理的异常穿透到非托管层。

  • 错误模块KERNELBASE.dll → 异常最终由 Windows 内核捕获,但根源可能在托管代码中。

  • 关键信息:

    • 进程: w3wp.exe(IIS 工作进程)。

    • 时间戳: KERNELBASE.dll 版本为 10.0.14393.5850(Windows Server 2016/Windows 10 版本 1607)。


2. 可能原因

  1. 托管代码未处理异常

    • 异步方法(async/await)中未正确捕获 Exception

    • 静态变量多线程竞争或资源泄漏

  2. 非托管代码交互问题

    • P/Invoke 或 COM 组件调用参数错误。

    • 非托管内存操作(如缓冲区溢出)。

  3. IIS/.NET Framework 兼容性问题

    • 异步操作与 IIS 模块(如 URL 重写、身份验证模块)冲突。

    • .NET Framework 版本缺陷(需确认是否安装最新补丁)。

  4. 第三方库缺陷

    • 异步上下文中使用的第三方库存在线程安全问题。

三、错误定位及解决方案 

我的程序经过排查,属于上述2.1.2 “静态变量多线程竞争或资源泄漏”的原因,在Task.Run()线程池内使用了非安全变量ViewBag和HttpContext.Current。

1. ViewBag 的生命周期

生命周期范围

  • 创建时机:在 Controller 的 Action 方法执行期间创建。

  • 存活范围:仅在当前 HTTP 请求的 ​Controller 到 View 渲染阶段​ 有效。

  • 销毁时机:当 View 渲染完成后,ViewBag 的数据会被释放。

核心特点

  • 动态对象ViewBag 是 dynamic 类型对象,用于在 Controller 和 View 之间传递数据。

  • 线程绑定ViewBag 仅在主请求线程(处理 Action 和 View 的线程)中有效,无法跨线程访问​(如 Task.Run 或异步方法中的子线程)。


2. HttpContext.Current 的生命周期

生命周期范围

  • 创建时机:HTTP 请求到达 ASP.NET 管道时创建。

  • 存活范围:贯穿 ​整个 HTTP 请求处理周期,包括中间件、控制器、视图等阶段。

  • 销毁时机:请求处理完成后,由 ASP.NET 运行时释放。

核心特点

  • 线程静态存储HttpContext.Current 通过 CallContext 实现线程关联性,仅在处理当前请求的线程中有效。

  • 异步兼容性问题:在异步代码中(如 async/await),线程切换可能导致 HttpContext.Current ​变为 null

具体错误代码如下:

public async Task<ActionResult> GetUser()
{
    await Task.Run(() => 
    {
        // 错误:子线程中 HttpContext.Current 可能为 null
        var user = HttpContext.Current.User.Identity.Name;
        //后续操作代码
    });
    await Task.Run(() => 
    {
        ViewBag.Message = 数据库读取内容; // 子线程写入:可能无法生效或导致竞争条件
    });
    return View();
}

应改为

public async Task<ActionResult> GetUser()
{
    var userName = HttpContext.Current.User.Identity.Name;
    await Task.Run(() => 
    {
        // 错误:子线程中 HttpContext.Current 可能为 null
        var user = userName ;
        //后续操作代码
    });
    string Message = "";
    await Task.Run(() => 
    {
        Message = 数据库读取内容; // 子线程写入:可能无法生效或导致竞争条件
    });
    ViewBag.Message = Message;
    return View();
}