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

如何在C# WinForms中实现SetDataFromSQL的暂停、继续与停止

C# WinForms 实现SQL数据处理的暂停/继续/停止控制

一、改造DefaultVariables类

需要添加停止信号、暂停控制的核心组件,并修改SetDataFromSQL方法加入控制检查逻辑。

1. 添加控制字段与初始化

using System.Data.SqlClient;
using System.Threading;
using System.Threading.Tasks;

public class DefaultVariables
{
    private CancellationTokenSource _cts;
    private ManualResetEventSlim _pauseEvent;

    // 进度更新事件(保留原有实现)
    public event EventHandler<ProgressEventArgs> ProgressChanged;

    public DefaultVariables()
    {
        // 初始化:停止信号未触发,初始状态为非暂停
        _cts = new CancellationTokenSource();
        _pauseEvent = new ManualResetEventSlim(true);
    }

2. 公开控制方法

// 暂停操作
    public void PauseOperation() => _pauseEvent.Reset();

    // 继续操作
    public void ResumeOperation() => _pauseEvent.Set();

    // 停止操作
    public void StopOperation()
    {
        _cts.Cancel();
        // 停止后恢复暂停状态,避免后续无法重启
        _pauseEvent.Set();
    }

    // 重置控制状态(重新执行前调用)
    public void ResetControls()
    {
        _cts.Dispose();
        _pauseEvent.Dispose();
        _cts = new CancellationTokenSource();
        _pauseEvent = new ManualResetEventSlim(true);
    }

3. 修改SetDataFromSQL方法,加入控制检查

public void SetDataFromSQL()
    {
        try
        {
            using (var conn = new SqlConnection("你的数据库连接字符串"))
            {
                conn.Open();
                var cmd = new SqlCommand("SELECT * FROM 目标表", conn);
                using (var reader = cmd.ExecuteReader())
                {
                    int processedRows = 0;
                    while (reader.Read())
                    {
                        // 优先检查停止信号,触发则终止
                        if (_cts.Token.IsCancellationRequested)
                        {
                            OnProgressChanged($"操作已停止,共处理{processedRows}行");
                            return;
                        }

                        // 等待暂停解除(同时监听停止信号,避免暂停时无法响应停止)
                        _pauseEvent.Wait(_cts.Token);

                        // 原有数据处理逻辑(比如赋值给变量)
                        // ...

                        processedRows++;
                        OnProgressChanged($"已处理{processedRows}行");
                    }
                    OnProgressChanged("操作完成");
                }
            }
        }
        catch (OperationCanceledException)
        {
            OnProgressChanged("操作已取消");
        }
        catch (Exception ex)
        {
            OnProgressChanged($"操作出错:{ex.Message}");
        }
    }

    // 封装进度事件触发(保留原有实现)
    private void OnProgressChanged(string message)
    {
        ProgressChanged?.Invoke(this, new ProgressEventArgs(message));
    }
}

// 进度事件参数类(保留原有实现)
public class ProgressEventArgs : EventArgs
{
    public string Message { get; }
    public ProgressEventArgs(string message) => Message = message;
}

二、WinForms 界面实现

1. 界面控件准备

添加以下控件:

  • 按钮:btnStart(开始)、btnPauseResume(暂停/继续)、btnStop(停止)
  • 标签:lblProgress(显示进度信息)

2. 界面代码逻辑

public partial class MainForm : Form
{
    private DefaultVariables _dataProcessor;
    private Task _operationTask;

    public MainForm()
    {
        InitializeComponent();
        // 初始禁用暂停/停止按钮
        btnPauseResume.Enabled = false;
        btnStop.Enabled = false;
    }

    // 开始按钮点击
    private void btnStart_Click(object sender, EventArgs e)
    {
        // 重置处理器状态,避免旧信号干扰
        _dataProcessor?.ResetControls();
        _dataProcessor = new DefaultVariables();
        _dataProcessor.ProgressChanged += DataProcessor_ProgressChanged;

        // 后台线程执行,不阻塞UI
        _operationTask = Task.Run(() => _dataProcessor.SetDataFromSQL());

        // 更新按钮状态
        btnStart.Enabled = false;
        btnPauseResume.Enabled = true;
        btnPauseResume.Text = "暂停";
        btnStop.Enabled = true;
    }

    // 暂停/继续按钮点击
    private void btnPauseResume_Click(object sender, EventArgs e)
    {
        if (btnPauseResume.Text == "暂停")
        {
            _dataProcessor.PauseOperation();
            btnPauseResume.Text = "继续";
            lblProgress.Text = "操作已暂停";
        }
        else
        {
            _dataProcessor.ResumeOperation();
            btnPauseResume.Text = "暂停";
            lblProgress.Text = "操作已继续";
        }
    }

    // 停止按钮点击
    private void btnStop_Click(object sender, EventArgs e)
    {
        _dataProcessor.StopOperation();
        // 等待任务结束,确保资源释放
        _operationTask.Wait();

        // 恢复按钮状态
        btnStart.Enabled = true;
        btnPauseResume.Enabled = false;
        btnStop.Enabled = false;
    }

    // 进度更新(必须回到UI线程)
    private void DataProcessor_ProgressChanged(object sender, ProgressEventArgs e)
    {
        if (lblProgress.InvokeRequired)
        {
            lblProgress.Invoke(new Action(() => lblProgress.Text = e.Message));
        }
        else
        {
            lblProgress.Text = e.Message;
        }
    }

    // 窗体关闭时清理资源
    private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
    {
        _dataProcessor?.StopOperation();
        _operationTask?.Wait();
        _dataProcessor?.ResetControls();
    }
}

三、核心要点说明

  • 停止控制:用CancellationTokenSource发送停止信号,在循环中检查IsCancellationRequested,触发后立即终止操作。
  • 暂停/继续控制:用ManualResetEventSlim实现等待逻辑,Reset()触发暂停,Set()恢复执行;Wait(_cts.Token)确保暂停时仍能响应停止请求。
  • 线程安全:所有UI更新必须通过Invoke切换到UI线程,避免跨线程操作异常。
  • 资源管理:停止操作或窗体关闭时,要释放CancellationTokenSource和ManualResetEventSlim的资源,防止内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 19:20:54