如何在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
相关产品推荐
相关产品推荐

