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

Visual Studio测试界面崩溃:单元测试触发StackOverflowException求助

问题

在Visual Studio中运行单元测试时,Test Explorer启动测试后出现异常标识,测试状态始终为蓝色(未执行完成状态),既不通过也不失败。输出窗口显示测试主机进程因StackOverflowException崩溃,但测试代码中未发现庞大调用栈或内存激增等典型栈溢出迹象。逐行调试至await Task.WhenAny(tasks).ConfigureAwait(false);这一行时,测试直接终止,无任何报错提示。

相关代码片段

public async Task StopAsync(CancellationToken ct)
{
   Logger.Information("Stopping consumers and workers...");

   try
   {
       try
       {
          _cancellationTokenSource.Cancel();
       }
       catch (Exception ex)
       {
           Logger.Error(ex, "Exception during cancellation of the AJQ consumers / workers");
       }

      var timeout = _config.Bootstrapper.StopServiceTimeout;
      Logger.Information($"Stop of worker/consumer tasks requested (waiting for: {timeout.TotalSeconds} sec for tasks to complete)");
      var delayTask = Task.Delay(timeout, ct);
      var waitAllTask = Task.WhenAll(AllTasks);
      var tasks = new[] { delayTask, waitAllTask };
      await Task.WhenAny(tasks).ConfigureAwait(false);
    }
    catch (Exception ex)
    {
      Logger.Error(ex, "Exception ... ");
    }
}

输出窗口错误信息

Building Test Projects
========== Starting test run ==========
The active test run was aborted. Reason: Test host process crashed : Process is terminated due 
to StackOverflowException.
Process is terminated due to StackOverflowException.
Process is terminated due to StackOverflowException.

========== Test run aborted: 0 Tests (0 Passed, 0 Failed, 0 Skipped) run in < 1 ms ==========

排查思路

  • 检查AllTasks中任务的取消逻辑:调用_cancellationTokenSource.Cancel()后,AllTasks里的任务可能触发连锁同步调用,比如任务响应取消时出现无限递归(如属性getter调用自身、事件触发后循环调用等),这类同步递归不会在异步栈中体现,容易被忽略。
  • 启用原生代码调试追踪栈溢出:在Visual Studio调试设置中开启“启用原生代码调试”,重新运行测试。StackOverflowException发生时,查看原生调用栈,找到递归源头——纯托管调试有时无法完整展示这类问题的调用链。
  • 验证StopServiceTimeout取值:如果timeout设为极小值(如0秒),Task.Delay会立即完成,但waitAllTask等待过程中可能触发同步阻塞逻辑,进而引发递归。可临时将timeout设为10秒,观察是否还会崩溃。
  • 定位AllTasks中的问题任务:逐个移除AllTasks中的任务,每次移除后运行测试,找到具体引发崩溃的任务,再检查其停止/取消逻辑是否存在同步递归、无限循环或重复触发取消回调的情况。
  • 排查日志框架的递归风险:Logger.Error写入日志时,是否存在内部递归(如日志写入失败时再次触发日志记录),这种情况会在异常发生时加剧栈溢出。可临时注释日志代码,测试是否还会崩溃。
  • 测试同步等待场景:把await Task.WhenAny(tasks).ConfigureAwait(false);替换为同步等待(如waitAllTask.Wait(timeout);),判断是异步等待触发的问题,还是任务本身的取消逻辑存在缺陷。

内容的提问来源于stack exchange,提问作者rbasniak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 11:30:59