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

C# Timer线程随机运行后抛出Thread was being aborted异常排查

故障根因

"Thread was being aborted." 对应CLR抛出的ThreadAbortException,这个异常不会被普通业务代码无意触发,只有两种触发可能:

  • 代码路径中存在主动调用Thread.Abort()的逻辑
  • 当前代码运行所在的AppDomain被卸载,对应你这个MVC项目的场景,就是IIS应用池回收、站点目录文件变更触发重启、内存占用超阈值触发回收这类宿主生命周期事件,这也是故障触发时间完全随机的核心原因——和你轮询的业务逻辑没有直接关系。

你现有代码里的几个设计缺陷,会把偶发的宿主生命周期事件变成线程永久停跑的故障:

  • PollingIfood方法用了错误的async void签名:方法内部没有任何await异步调用,加async关键字属于多余写法。System.Threading.Timer的回调本身是跑在线程池工作线程上的同步委托,async void会导致回调内的异常逃逸出Timer的执行上下文,一旦抛出异常直接打断执行流,没有兜底机会。
  • 静态Timer的生命周期管理有漏洞:Timer实例是静态字段初始化的,但Reiniciar()方法重置单例的时候,没有主动Dispose旧的Timer实例,旧Timer要么被GC回收后停止触发,要么和新创建的Timer产生执行冲突。
  • 没有针对ThreadAbortException做特殊处理:这个异常是CLR特殊处理的异常,哪怕被catch块捕获,catch执行完后CLR会自动重新抛出,你现在的catch只打日志,没有调用Thread.ResetAbort()取消中止标记,会导致finally块里重置Timer的逻辑执行被打断,Timer直接停在无限等待状态,再也不会触发下一轮轮询。
  • 没有适配IIS的应用生命周期:ASP.NET跑在IIS上时,默认就有空闲超时回收、固定时间回收、文件变更触发重启的机制,你没有注册AppDomain卸载的监听事件,完全感知不到宿主即将关闭的信号,只能等线程被强制Abort。
修复方案

按以下步骤调整即可解决问题:

  1. 去掉PollingIfood的async修饰符,匹配Timer原生回调签名,避免async void的异常逃逸问题。
  2. 修正单例重置逻辑:Reiniciar()方法执行时先Dispose旧的Timer实例,再重置状态,避免产生游离的Timer对象。
  3. 异常捕获单独处理ThreadAbortException,捕获后调用Thread.ResetAbort()取消CLR的线程中止标记,保证finally块的Timer重置逻辑能正常执行。
  4. 调整Timer初始化时机:不要在静态字段声明时直接创建Timer,放到Inicializa()方法里加锁初始化,避免静态构造时机不确定带来的异常。
  5. 注册AppDomain的DomainUnload事件,感知宿主卸载动作,主动释放Timer资源。
  6. 调整IIS站点配置:将应用池空闲超时设为0,开启应用池「始终运行」模式、站点预加载,把应用池固定回收时间设置到业务低峰期,减少随机回收的概率。

修正后的核心代码如下:

using System.Threading;
namespace NewMVC.infraestructure
{
    public class Thread_iFood
    {
        private static bool inicializado = false;
        static Thread_iFood instance = null;
        static readonly object padlock = new object();
        private const int timer = 30000;
        static Timer thProcessaRet = null;
        private Thread_iFood()
        {
            // 监听应用域卸载事件,提前感知宿主回收
            AppDomain.CurrentDomain.DomainUnload += (s, e) => 
            {
                thProcessaRet?.Dispose();
                thProcessaRet = null;
            };
        }
        public static void Reiniciar()
        {
            lock (padlock)
            {
                thProcessaRet?.Dispose();
                thProcessaRet = null;
                inicializado = false;
                instance = null;
            }
        }
        public static Thread_iFood GetInstance
        {
            get
            {
                if (instance == null)
                {
                    lock (padlock)
                    {
                        instance ??= new Thread_iFood();
                    }
                }
                return instance;
            }
        }
        // 移除async关键字,匹配TimerCallback委托签名
        internal static void PollingIfood(Object obj)
        {
            try
            {
                thProcessaRet.Change(Timeout.Infinite, Timeout.Infinite);
                MetodosAuxiliares.BuscaPedidosIFood();
            }
            catch (ThreadAbortException tae)
            {
                // 重置线程中止标记,阻止CLR自动重抛异常
                Thread.ResetAbort();
                LogErros.GravaLog(tae, "Thread_iFood/PollingIfood 触发线程中止,已重置标记");
            }
            catch (Exception e)
            {
                LogErros.GravaLog(e, "Thread_iFood/PollingIfood");
            }
            finally
            {
                thProcessaRet?.Change(timer, Timeout.Infinite);
            }
        }
        public void Inicializa()
        {
            if (!inicializado)
            {
                lock (padlock)
                {
                    if (!inicializado)
                    {
                        thProcessaRet ??= new Timer(PollingIfood, null, Timeout.Infinite, Timeout.Infinite);
                        thProcessaRet.Change(timer, Timeout.Infinite);
                        inicializado = true;
                    }
                }
            }
        }
    }
}

注意:IIS本身是为处理HTTP请求设计的宿主,天生存在应用回收机制,如果你的轮询任务是核心业务链路,最稳妥的方案是把轮询逻辑单独拆成Windows服务或者独立后台服务部署,不要直接挂在MVC站点的进程里跑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 13:48:20