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

类级别声明CancellationTokenSource触发BadImageFormatException问题排查

问题描述

我有一个包含长时间运行任务的类,该任务需在UI线程触发的按钮点击时取消。为此我在类级别声明了CancellationTokenSource,启动任务时获取CancellationToken传入,取消时调用Cancel方法。但补丁更新后,点击启动任务的按钮时应用崩溃,抛出BadImageFormatException异常。请问我哪里操作有误?

public class TaskRunner
{
   private CancellationTokenSource ctSource = new CancellationTokenSource();
   private Task _task; 
   private bool _isTaskPerforming = true; 
  
   public async void BeginTask()
   {
     var ct = ctSource.Token;

     await PerformTask(ct);
   }
   
   private async Task PerformTask(CancellationToken ct)
   {
      _task = Task.Run(() =>
         {
            while(_isTaskPerforming)
            {
               //Perform task related functions
               //Check for cancellation
               if(ct.IsCancellationRequested)
               {
                   _isTaskPerforming = false;
                   //other cleanup
               }
            }
         },ct);
   }

   public void CancelTask()
   {
      ctSource.Cancel();
   }
}

注:BeginTask和CancelTask均由引用该DLL的WPF应用按钮点击事件处理程序调用。


问题分析与解决方案

BadImageFormatException大多和程序集位数不匹配、损坏或版本兼容问题有关,但你的代码逻辑也存在多个关键问题,这些问题可能在补丁更新后触发异常,或与环境变化共同导致崩溃:

核心代码问题

  • CancellationTokenSource未重置:类级别的ctSource在调用Cancel()后就处于取消状态,无法复用。再次点击启动按钮时,传入的CancellationToken已失效,会导致任务异常。
  • 异步方法未正确等待:PerformTask标记为async Task但未内部await任何操作,会导致BeginTask中的await直接完成,后台任务脱离管控,还会隐藏异常。
  • 线程安全隐患:_isTaskPerforming为未同步的共享字段,后台线程和UI线程同时访问会引发竞争条件,导致不可预期行为。
  • 取消逻辑不规范:未使用TPL标准的ct.ThrowIfCancellationRequested()触发任务取消,手动修改状态的方式不符合异步任务的取消规范。

修复后的代码

public class TaskRunner
{
   private CancellationTokenSource _ctSource;
   private Task _task; 
   private readonly object _lockObj = new object();
   private bool _isTaskPerforming; 
  
   public async Task BeginTask()
   {
       // 防止重复启动任务
       lock (_lockObj)
       {
           if (_isTaskPerforming) return;
           _ctSource = new CancellationTokenSource();
           _isTaskPerforming = true;
       }

       try
       {
           await PerformTask(_ctSource.Token);
       }
       finally
       {
           // 确保任务结束后清理资源
           lock (_lockObj)
           {
               _isTaskPerforming = false;
               _ctSource?.Dispose();
               _ctSource = null;
           }
       }
   }
   
   private async Task PerformTask(CancellationToken ct)
   {
       // 正确await后台任务,确保异步流程可控
       await Task.Run(() =>
       {
           while (!ct.IsCancellationRequested)
           {
               // 执行任务相关操作
               // 可添加适当延迟避免CPU占用过高,比如Thread.Sleep(100);
               
               // 中途检查取消,符合TPL规范
               ct.ThrowIfCancellationRequested();
           }
           // 任务结束或取消后的清理操作放在此处
       }, ct);
   }

   public void CancelTask()
   {
       lock (_lockObj)
       {
           _ctSource?.Cancel();
       }
   }
}

BadImageFormatException排查步骤

  • 确认DLL与WPF应用的目标平台一致(均为x86、x64或Any CPU)
  • 检查补丁更新后是否替换了错误版本的依赖程序集
  • 清理解决方案并重新生成所有项目,清除残留的旧程序集
  • 排查第三方库在补丁更新后是否出现位数不兼容问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 18:05:17