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

窗口关闭时如何正确终止任务与进程?解决频繁重开异常

问题解决方案

核心问题分析

频繁快速重开窗口时出现“任务已取消或释放”报错,主要原因是:

  • 窗口关闭时未检查CancellationTokenSource状态就直接调用Cancel()和Dispose(),触发重复操作已释放对象的异常
  • 异步任务未正确响应取消信号,且Start()方法存在语法错误
  • 进程终止逻辑顺序不合理,未判断进程是否仍在运行

修正方案

1. 优化CancellationTokenSource生命周期管理

窗口关闭时先检查CancellationTokenSource状态,避免重复执行取消/释放操作;调整操作顺序,先取消任务再释放资源。

2. 实现异步任务的取消响应

在任务执行过程中定期检查取消令牌,确保任务能及时终止;修正Start()方法的语法错误,正确传递取消令牌。

3. 规范进程终止逻辑

先判断进程是否处于运行状态,再调用Kill(),并等待进程完全终止后再释放资源,避免操作已结束的进程。

修改后的代码

class MyAdditionalWindowClass
{
    private CancellationTokenSource _cts;
    private Process _process;

    public MyAdditionalWindowClass()
    {
        _cts = new CancellationTokenSource();
        Start();
        this.Closed += OnWindowClosed;
    }

    private async void Start()
    {
        try
        {
            await Task.Run(() => ToDoSomething(_cts.Token), _cts.Token);
            // 后续代码需先检查取消状态
            if (_cts.Token.IsCancellationRequested) return;
            // 其他业务逻辑
        }
        catch (OperationCanceledException)
        {
            // 任务取消的常规处理,无需抛出异常
        }
    }

    private void ToDoSomething(CancellationToken token)
    {
        // 创建进程前先检查取消信号
        token.ThrowIfCancellationRequested();
        
        _process = new Process();
        // 配置进程启动参数
        _process.StartInfo = new ProcessStartInfo("你的可执行文件路径")
        {
            UseShellExecute = false,
            CreateNoWindow = true
        };

        _process.Start();

        // 循环检查取消信号,同时等待进程结束
        while (!_process.HasExited)
        {
            token.ThrowIfCancellationRequested();
            Thread.Sleep(100); // 短间隔轮询,减少资源占用
        }
    }

    private void OnWindowClosed(object sender, EventArgs e)
    {
        // 终止并清理进程
        if (_process != null && !_process.HasExited)
        {
            try
            {
                _process.Kill();
                _process.WaitForExit(1000); // 等待1秒确保进程终止
            }
            catch (InvalidOperationException)
            {
                // 进程已终止的异常处理
            }
            finally
            {
                _process.Close();
                _process.Dispose();
                _process = null;
            }
        }

        // 处理CancellationTokenSource
        if (_cts != null)
        {
            try
            {
                if (!_cts.IsCancellationRequested)
                {
                    _cts.Cancel();
                }
            }
            catch (ObjectDisposedException)
            {
                // 已释放的情况无需处理
            }
            finally
            {
                _cts.Dispose();
                _cts = null;
            }
        }
    }
}

关键改动说明

  • 将匿名事件处理改为命名方法OnWindowClosed,提升代码可读性
  • 在ToDoSomething()中添加token.ThrowIfCancellationRequested(),确保任务及时响应取消
  • 进程终止时增加状态检查和等待逻辑,避免操作已终止的进程
  • 对CancellationTokenSource的操作添加异常捕获,处理重复释放/取消的场景
  • 修正Task.Run的语法错误,正确传递取消令牌

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 17:40:48