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

C# WinForm点击按钮强制终止ParseXlM类文件解析处理任务方法

实现方案

核心思路

使用.NET 自带的CancellationTokenSource+CancellationToken实现协作式取消,同时将长时间运行的解析逻辑放到后台线程执行,避免阻塞UI导致取消按钮无法响应。协作式取消是业务逻辑主动判断取消信号的方案,比强制终止线程更安全,不会出现资源泄漏、数据损坏的问题。

第一步:改造文件解析业务类

给解析方法新增取消令牌入参,在循环内主动判断是否收到取消信号:

namespace oarch.classes
{
    public class ParseXlM
    {
        // 新增CancellationToken类型入参
        public static DataTable ParseXlM2(string dbfFile, System.Text.Encoding readingEncoding,ListBox olistBox1,ListBox elistBox, System.Windows.Forms.Label nlabel, CancellationToken cancellationToken)
        {
            // 原有初始化逻辑省略
            for (int i =0 ;;)
            {
                // 新增取消判断:收到取消信号则抛出异常终止执行
                cancellationToken.ThrowIfCancellationRequested();

                // 原有循环处理逻辑省略
                // 注意:如果有更新UI的操作,需要用控件.Invoke回到主线程执行,避免跨线程异常
            }
            // 原有返回逻辑省略
        } 
    }
}

第二步:改造窗体代码,新增取消控制逻辑

先在窗体上新增终止按钮(名称设为btnCancel),再修改窗体代码如下:

namespace oarch.xmlSql
{
    public partial class ReadXML : Form
    {
        // 全局声明取消令牌源,用于发送取消信号
        private CancellationTokenSource _cts;

        public ReadXML()
        {
            InitializeComponent();
            // 初始状态下取消按钮不可点击
            btnCancel.Enabled = false;
        }

        // 原有解析触发按钮的点击事件,改造成异步方法
        private async void buttiClick(object sender, EventArgs e)
        {
            _cts = new CancellationTokenSource();
            // 任务执行中切换按钮状态
            btnCancel.Enabled = true;
            butti.Enabled = false;
            DataTable parseResult = null;
            try
            {
                // 把解析逻辑放到后台线程执行,不阻塞UI
                parseResult = await Task.Run(() =>
                {
                    return classes.ParseXlM.ParseXlM2(FileNameStr, System.Text.Encoding.GetEncoding(eCodepage),listBox1,listBox2, label6, _cts.Token);
                }, _cts.Token);

                // 解析完成后的后续业务逻辑省略,比如绑定数据到控件
            }
            catch (OperationCanceledException)
            {
                MessageBox.Show("文件解析已被手动终止");
            }
            catch (Exception ex)
            {
                MessageBox.Show($"解析出错:{ex.Message}");
            }
            finally
            {
                // 释放资源,恢复按钮状态
                _cts.Dispose();
                btnCancel.Enabled = false;
                butti.Enabled = true;
            }
        }

        // 新增终止按钮的点击事件
        private void btnCancel_Click(object sender, EventArgs e)
        {
            // 发送取消信号
            _cts?.Cancel();
        }
    }  
}

注意事项

  • 解析逻辑里如果有直接操作UI控件的代码,必须改为通过控件Invoke方法封送到主线程执行,否则会抛出跨线程操作异常
  • 循环内的取消判断尽量放在每次迭代的最开头,保证取消请求可以被及时响应
  • 禁止使用Thread.Abort这类强制终止线程的方法,会导致文件句柄未释放、内存泄漏等不可预期的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 14:27:03