开源 C# 快速开发(十一)线程
文章的目的为了记录使用C# 开发学习的经历。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。
相关链接:
开源 C# 快速开发(一)基础知识
开源 C# 快速开发(二)基础控件
开源 C# 快速开发(三)复杂控件
开源 C# 快速开发(四)自定义控件--波形图
开源 C# 快速开发(五)自定义控件--仪表盘
开源 C# 快速开发(六)自定义控件--圆环
开源 C# 快速开发(七)通讯--串口
开源 C# 快速开发(八)通讯--Tcp服务器端
开源 C# 快速开发(九)通讯--Tcp客户端
开源 C# 快速开发(十)通讯--http客户端
开源 C# 快速开发(十一)线程
开源 C# 快速开发(十二)进程监控
推荐链接:
开源 C# .net mvc 开发(一)WEB搭建_c#部署web程序-CSDN博客
开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-CSDN博客
开源 C# .net mvc 开发(三)WEB内外网访问-CSDN博客
开源 C# .net mvc 开发(四)工程结构、页面提交以及显示-CSDN博客
开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-CSDN博客
开源 C# .net mvc 开发(六)发送邮件、定时以及CMD编程-CSDN博客
开源 C# .net mvc 开发(七)动态图片、动态表格和json数据生成-CSDN博客
开源 C# .net mvc 开发(八)IIS Express轻量化Web服务器的配置和使用-CSDN博客
开源 C# .net mvc 开发(九)websocket--服务器与客户端的实时通信-CSDN博客
本章节主要内容是:C#多线程编程的示例,演示了线程在不同场景下的用处和用法
在C#中,线程(Thread) 是程序执行流的最小单元,是进程中的一个独立执行路径
什么是线程?
// 线程是进程内的独立执行单元
进程 (Process) = 资源容器(内存、文件句柄等)
↓
线程 (Thread) = 实际的代码执行流(一个进程可以有多个线程)
// 比喻理解:
- 进程就像一家公司(拥有办公空间、设备等资源)
- 线程就像公司里的员工(各自执行不同的任务,共享公司资源)
线程的核心特点
❖ 共享进程的内存和资源
❖ 拥有独立的执行栈和寄存器状态
❖ 是CPU调度的基本单位
❖ 可以并发或并行执行
❖ 线程间通信比进程间通信简单高效
用途:
提高程序响应性
并行计算和性能提升
后台任务处理
目录:
1.源码分析
2.所有源码
3.效果演示
一、源码分析
Form1.cs 详细分析
1. 字段和构造函数
字段声明
private static readonly object _lockObject = new object();
private static int _sharedCounter = 0;
private CancellationTokenSource _cancellationTokenSource;
private int _completedTasks = 0;
作用:
_lockObject:线程同步的锁对象
_sharedCounter:演示线程同步的共享计数器
_cancellationTokenSource:任务取消令牌源
_completedTasks:跟踪完成的任务数量
构造函数
public Form1()
{InitializeComponent();_cancellationTokenSource = new CancellationTokenSource();UpdateStatus("程序已就绪");
}
作用:
调用 InitializeComponent() 初始化界面
创建取消令牌源实例
设置初始状态
2. 核心演示方法
2.1 btnPerformanceTest_Click - 性能测试
private async void btnPerformanceTest_Click(object sender, EventArgs e)
{UpdateStatus("性能测试运行中...");AppendOutput("1. 单线程 vs 多线程性能对比");// ... 性能测试逻辑
}
工作流程:
更新状态显示
输出测试标题
准备测试数据
分别执行单线程和多线程处理
比较并显示耗时结果
2.2 ProcessDataSingleThreaded - 单线程处理
private async Task ProcessDataSingleThreaded(int[] data)
{await Task.Run(() =>{for (int i = 0; i < data.Length; i++){data[i] = (int)Math.Sqrt(data[i] * Math.PI) % 1000;}});
}
技术要点:
使用 Task.Run 在后台线程执行以避免阻塞UI
模拟CPU密集型计算
await 确保异步完成
2.3 ProcessDataMultiThreaded - 多线程处理
private async Task ProcessDataMultiThreaded(int[] data)
{int chunkSize = data.Length / Environment.ProcessorCount;var tasks = new List<Task>();for (int i = 0; i < Environment.ProcessorCount; i++){int start = i * chunkSize;int end = (i == Environment.ProcessorCount - 1) ? data.Length : start + chunkSize;tasks.Add(Task.Run(() =>{for (int j = start; j < end; j++){data[j] = (int)Math.Sqrt(data[j] * Math.PI) % 1000;}}));}await Task.WhenAll(tasks);
}
技术要点:
数据分块:将大数据集分成多个块
并行处理:每个块在单独的Task中处理
Task.WhenAll:等待所有任务完成
利用多核CPU优势
2.4 btnBackgroundTask_Click - 后台任务演示
private void btnBackgroundTask_Click(object sender, EventArgs e)
{UpdateStatus("后台任务运行中...");AppendOutput("2. 后台任务演示");// 禁用按钮防止重复点击btnBackgroundTask.Enabled = false;var backgroundTask = Task.Run(async () =>{for (int i = 1; i <= 5; i++){if (_cancellationTokenSource.Token.IsCancellationRequested)break;var message = $"后台任务工作: 第 {i} 次循环";AppendOutputThreadSafe(message);await Task.Delay(1000);}// ... 完成后重新启用按钮});
}
技术要点:
按钮状态管理:防止重复提交
取消令牌检查:支持任务取消
线程安全输出:使用 AppendOutputThreadSafe
2.5 btnThreadSync_Click - 线程同步演示
private void btnThreadSync_Click(object sender, EventArgs e)
{_sharedCounter = 0;var tasks = new List<Task>();for (int i = 0; i < 5; i++){int threadNumber = i + 1;tasks.Add(Task.Run(() => IncrementCounter(threadNumber)));}Task.Run(async () =>{await Task.WhenAll(tasks);AppendOutputThreadSafe($"最终计数器值: {_sharedCounter} (应该是 50000)");});
}
2.6 IncrementCounter - 计数器递增
private void IncrementCounter(int threadNumber)
{for (int i = 0; i < 10000; i++){// 使用锁确保线程安全lock (_lockObject){_sharedCounter++;}}AppendOutputThreadSafe($"线程-{threadNumber} 完成工作");
}
技术要点:
lock 关键字:确保对共享资源的互斥访问
防止竞态条件
演示没有锁时会出现的数据不一致问题
2.7 btnProducerConsumer_Click - 生产者消费者模式
var producer = Task.Run(async () =>
{for (int i = 0; i < totalItems; i++){lock (_lockObject){while (queue.Count >= maxSize){Monitor.Wait(_lockObject); // 等待队列有空位}queue.Enqueue(i);Monitor.PulseAll(_lockObject); // 通知消费者}await Task.Delay(100);}
});
技术要点:
Monitor.Wait/PulseAll:线程间通信
缓冲区管理:防止队列溢出
协调生产者和消费者的速度差异
3. 线程安全辅助方法
3.1 AppendOutput - 线程安全输出
private void AppendOutput(string text)
{if (txtOutput.InvokeRequired){txtOutput.Invoke(new Action<string>(AppendOutput), text);}else{txtOutput.AppendText(text + Environment.NewLine);txtOutput.ScrollToCaret();}
}
技术要点:
InvokeRequired:检查是否需要在UI线程执行
Control.Invoke:跨线程调用UI更新
ScrollToCaret:自动滚动到最新内容
3.2 UpdateProgressBarThreadSafe - 进度条更新
private void UpdateProgressBarThreadSafe(int value)
{if (progressBar1.InvokeRequired){progressBar1.Invoke(new Action<int>(UpdateProgressBarThreadSafe), value);}else{progressBar1.Value = Math.Min(value, progressBar1.Maximum);lblProgress.Text = $"任务进度: {value}%";}
}
技术要点:
进度值和标签文本同步更新
防止进度值超出范围
3.3 UpdateStatus - 状态栏更新
private void UpdateStatus(string status)
{if (lblStatus.InvokeRequired){lblStatus.Invoke(new Action<string>(UpdateStatus), status);}else{lblStatus.Text = status;}
}
作用:提供用户友好的状态反馈。
4. 任务管理方法
4.1 btnCancelTasks_Click - 取消任务
private void btnCancelTasks_Click(object sender, EventArgs e)
{AppendOutput("取消所有任务...");_cancellationTokenSource.Cancel();_cancellationTokenSource = new CancellationTokenSource();UpdateStatus("已发送取消请求");btnBackgroundTask.Enabled = true;
}
技术要点:
CancellationTokenSource.Cancel():发送取消信号
创建新的令牌源:为后续任务准备
恢复按钮状态
4.2 Form1_FormClosing - 窗体关闭处理
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{_cancellationTokenSource?.Cancel();
}
作用:确保程序退出时所有后台任务被正确取消。
二、所有源码
Form1.Designer.cs源码
using System.Drawing;
using System.Windows.Forms;namespace _10_thread
{partial class Form1{/// <summary>/// Required designer variable./// </summary>private System.ComponentModel.IContainer components = null;/// <summary>/// Clean up any resources being used./// </summary>/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows Form Designer generated code/// <summary>/// Required method for Designer support - do not modify/// the contents of this method with the code editor./// </summary>private void InitializeComponent(){btnPerformanceTest = new Button();btnBackgroundTask = new Button();btnThreadSync = new Button();btnProducerConsumer = new Button();btnParallelProcessing = new Button();btnCancelTasks = new Button();btnClear = new Button();txtOutput = new TextBox();progressBar1 = new ProgressBar();lblProgress = new Label();groupBox1 = new GroupBox();groupBox2 = new GroupBox();lblStatus = new Label();groupBox1.SuspendLayout();groupBox2.SuspendLayout();SuspendLayout();// // btnPerformanceTest// btnPerformanceTest.BackColor = Color.LightBlue;btnPerformanceTest.Location = new Point(16, 26);btnPerformanceTest.Margin = new Padding(4);btnPerformanceTest.Name = "btnPerformanceTest";btnPerformanceTest.Size = new Size(150, 40);btnPerformanceTest.TabIndex = 0;btnPerformanceTest.Text = "1. 性能测试";btnPerformanceTest.UseVisualStyleBackColor = false;btnPerformanceTest.Click += btnPerformanceTest_Click;// // btnBackgroundTask// btnBackgroundTask.BackColor = Color.LightBlue;btnBackgroundTask.Location = new Point(174, 26);btnBackgroundTask.Margin = new Padding(4);btnBackgroundTask.Name = "btnBackgroundTask";btnBackgroundTask.Size = new Size(150, 40);btnBackgroundTask.TabIndex = 1;btnBackgroundTask.Text = "2. 后台任务";btnBackgroundTask.UseVisualStyleBackColor = false;btnBackgroundTask.Click += btnBackgroundTask_Click;// // btnThreadSync// btnThreadSync.BackColor = Color.LightBlue;btnThreadSync.Location = new Point(332, 26);btnThreadSync.Margin = new Padding(4);btnThreadSync.Name = "btnThreadSync";btnThreadSync.Size = new Size(150, 40);btnThreadSync.TabIndex = 2;btnThreadSync.Text = "3. 线程同步";btnThreadSync.UseVisualStyleBackColor = false;btnThreadSync.Click += btnThreadSync_Click;// // btnProducerConsumer// btnProducerConsumer.BackColor = Color.LightBlue;btnProducerConsumer.Location = new Point(490, 26);btnProducerConsumer.Margin = new Padding(4);btnProducerConsumer.Name = "btnProducerConsumer";btnProducerConsumer.Size = new Size(150, 40);btnProducerConsumer.TabIndex = 3;btnProducerConsumer.Text = "4. 生产者-消费者";btnProducerConsumer.UseVisualStyleBackColor = false;btnProducerConsumer.Click += btnProducerConsumer_Click;// // btnParallelProcessing// btnParallelProcessing.BackColor = Color.LightBlue;btnParallelProcessing.Location = new Point(648, 26);btnParallelProcessing.Margin = new Padding(4);btnParallelProcessing.Name = "btnParallelProcessing";btnParallelProcessing.Size = new Size(150, 40);btnParallelProcessing.TabIndex = 4;btnParallelProcessing.Text = "5. 并行处理";btnParallelProcessing.UseVisualStyleBackColor = false;btnParallelProcessing.Click += btnParallelProcessing_Click;// // btnCancelTasks// btnCancelTasks.BackColor = Color.LightCoral;btnCancelTasks.Location = new Point(16, 85);btnCancelTasks.Margin = new Padding(4);btnCancelTasks.Name = "btnCancelTasks";btnCancelTasks.Size = new Size(150, 40);btnCancelTasks.TabIndex = 5;btnCancelTasks.Text = "取消所有任务";btnCancelTasks.UseVisualStyleBackColor = false;btnCancelTasks.Click += btnCancelTasks_Click;// // btnClear// btnClear.BackColor = Color.LightGreen;btnClear.Location = new Point(174, 85);btnClear.Margin = new Padding(4);btnClear.Name = "btnClear";btnClear.Size = new Size(150, 40);btnClear.TabIndex = 6;btnClear.Text = "清空输出";btnClear.UseVisualStyleBackColor = false;btnClear.Click += btnClear_Click;// // txtOutput// txtOutput.BackColor = Color.Black;txtOutput.Font = new Font("Consolas", 9.75F, FontStyle.Regular, GraphicsUnit.Point, 0);txtOutput.ForeColor = Color.White;txtOutput.Location = new Point(16, 28);txtOutput.Margin = new Padding(4);txtOutput.Multiline = true;txtOutput.Name = "txtOutput";txtOutput.ReadOnly = true;txtOutput.ScrollBars = ScrollBars.Vertical;txtOutput.Size = new Size(968, 438);txtOutput.TabIndex = 7;// // progressBar1// progressBar1.Location = new Point(490, 92);progressBar1.Margin = new Padding(4);progressBar1.Name = "progressBar1";progressBar1.Size = new Size(308, 27);progressBar1.TabIndex = 8;// // lblProgress// lblProgress.AutoSize = true;lblProgress.Location = new Point(332, 96);lblProgress.Margin = new Padding(4, 0, 4, 0);lblProgress.Name = "lblProgress";lblProgress.Size = new Size(150, 20);lblProgress.TabIndex = 9;lblProgress.Text = "任务进度: 0%";// // groupBox1// groupBox1.Controls.Add(btnPerformanceTest);groupBox1.Controls.Add(lblProgress);groupBox1.Controls.Add(btnBackgroundTask);groupBox1.Controls.Add(progressBar1);groupBox1.Controls.Add(btnThreadSync);groupBox1.Controls.Add(btnCancelTasks);groupBox1.Controls.Add(btnProducerConsumer);groupBox1.Controls.Add(btnClear);groupBox1.Controls.Add(btnParallelProcessing);groupBox1.Dock = DockStyle.Top;groupBox1.Location = new Point(0, 0);groupBox1.Margin = new Padding(4);groupBox1.Name = "groupBox1";groupBox1.Padding = new Padding(4);groupBox1.Size = new Size(1000, 140);groupBox1.TabIndex = 10;groupBox1.TabStop = false;groupBox1.Text = "线程演示控制";// // groupBox2// groupBox2.Controls.Add(txtOutput);groupBox2.Dock = DockStyle.Fill;groupBox2.Location = new Point(0, 140);groupBox2.Margin = new Padding(4);groupBox2.Name = "groupBox2";groupBox2.Padding = new Padding(4);groupBox2.Size = new Size(1000, 484);groupBox2.TabIndex = 11;groupBox2.TabStop = false;groupBox2.Text = "输出信息";// // lblStatus// lblStatus.BackColor = SystemColors.Info;lblStatus.BorderStyle = BorderStyle.FixedSingle;lblStatus.Dock = DockStyle.Bottom;lblStatus.Location = new Point(0, 624);lblStatus.Margin = new Padding(4, 0, 4, 0);lblStatus.Name = "lblStatus";lblStatus.Size = new Size(1000, 28);lblStatus.TabIndex = 12;lblStatus.Text = "就绪";lblStatus.TextAlign = ContentAlignment.MiddleLeft;// // Form1// AutoScaleDimensions = new SizeF(9F, 20F);AutoScaleMode = AutoScaleMode.Font;ClientSize = new Size(1000, 652);Controls.Add(groupBox2);Controls.Add(groupBox1);Controls.Add(lblStatus);Margin = new Padding(4);MinimumSize = new Size(1018, 699);Name = "Form1";Text = "C# 多线程演示程序";FormClosing += Form1_FormClosing;groupBox1.ResumeLayout(false);groupBox1.PerformLayout();groupBox2.ResumeLayout(false);groupBox2.PerformLayout();ResumeLayout(false);}#endregionprivate Button btnPerformanceTest;private Button btnBackgroundTask;private Button btnThreadSync;private Button btnProducerConsumer;private Button btnParallelProcessing;private Button btnCancelTasks;private Button btnClear;private TextBox txtOutput;private ProgressBar progressBar1;private Label lblProgress;private GroupBox groupBox1;private GroupBox groupBox2;private Label lblStatus;}
}
Form1.cs源码
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;namespace _10_thread
{public partial class Form1 : Form{private static readonly object _lockObject = new object();private static int _sharedCounter = 0;private CancellationTokenSource _cancellationTokenSource;private int _completedTasks = 0;public Form1(){InitializeComponent();_cancellationTokenSource = new CancellationTokenSource();UpdateStatus("程序已就绪");}// 1. 性能对比演示private async void btnPerformanceTest_Click(object sender, EventArgs e){UpdateStatus("性能测试运行中...");AppendOutput("1. 单线程 vs 多线程性能对比");AppendOutput("---------------------------");int[] data = Enumerable.Range(1, 1000000).ToArray(); // 减少数据量以适应UI演示// 单线程处理var stopwatch = System.Diagnostics.Stopwatch.StartNew();await ProcessDataSingleThreaded(data);stopwatch.Stop();AppendOutput($"单线程处理时间: {stopwatch.ElapsedMilliseconds} ms");// 多线程处理stopwatch.Restart();await ProcessDataMultiThreaded(data);stopwatch.Stop();AppendOutput($"多线程处理时间: {stopwatch.ElapsedMilliseconds} ms");AppendOutput("");UpdateStatus("性能测试完成");}private async Task ProcessDataSingleThreaded(int[] data){await Task.Run(() =>{for (int i = 0; i < data.Length; i++){data[i] = (int)Math.Sqrt(data[i] * Math.PI) % 1000;}});}private async Task ProcessDataMultiThreaded(int[] data){int chunkSize = data.Length / Environment.ProcessorCount;var tasks = new List<Task>();for (int i = 0; i < Environment.ProcessorCount; i++){int start = i * chunkSize;int end = (i == Environment.ProcessorCount - 1) ? data.Length : start + chunkSize;tasks.Add(Task.Run(() =>{for (int j = start; j < end; j++){data[j] = (int)Math.Sqrt(data[j] * Math.PI) % 1000;}}));}await Task.WhenAll(tasks);}// 2. 后台任务演示private void btnBackgroundTask_Click(object sender, EventArgs e){UpdateStatus("后台任务运行中...");AppendOutput("2. 后台任务演示");AppendOutput("---------------");// 禁用按钮防止重复点击btnBackgroundTask.Enabled = false;// 使用 Task 创建后台任务var backgroundTask = Task.Run(async () =>{for (int i = 1; i <= 5; i++){if (_cancellationTokenSource.Token.IsCancellationRequested)break;var message = $"后台任务工作: 第 {i} 次循环";AppendOutputThreadSafe(message);UpdateStatus($"后台任务运行中... ({i}/5)");await Task.Delay(1000);}if (!_cancellationTokenSource.Token.IsCancellationRequested){AppendOutputThreadSafe("后台任务完成");UpdateStatus("后台任务完成");Invoke(new Action(() => btnBackgroundTask.Enabled = true));}});}// 3. 线程同步演示private void btnThreadSync_Click(object sender, EventArgs e){UpdateStatus("线程同步演示运行中...");AppendOutput("3. 线程同步演示");AppendOutput("---------------");_sharedCounter = 0;var tasks = new List<Task>();// 创建多个任务同时访问共享资源for (int i = 0; i < 5; i++){int threadNumber = i + 1;tasks.Add(Task.Run(() => IncrementCounter(threadNumber)));}// 等待所有任务完成Task.Run(async () =>{await Task.WhenAll(tasks);AppendOutputThreadSafe($"最终计数器值: {_sharedCounter} (应该是 50000)");AppendOutputThreadSafe("");UpdateStatus("线程同步演示完成");});}private void IncrementCounter(int threadNumber){for (int i = 0; i < 10000; i++){// 使用锁确保线程安全lock (_lockObject){_sharedCounter++;}}AppendOutputThreadSafe($"线程-{threadNumber} 完成工作");}// 4. 生产者-消费者模式演示private void btnProducerConsumer_Click(object sender, EventArgs e){UpdateStatus("生产者-消费者模式运行中...");AppendOutput("4. 生产者-消费者模式演示");AppendOutput("-----------------------");var queue = new Queue<int>();const int maxSize = 5;const int totalItems = 10;// 生产者任务var producer = Task.Run(async () =>{for (int i = 0; i < totalItems; i++){if (_cancellationTokenSource.Token.IsCancellationRequested)break;lock (_lockObject){while (queue.Count >= maxSize){Monitor.Wait(_lockObject);}queue.Enqueue(i);AppendOutputThreadSafe($"生产者生产: {i}");Monitor.PulseAll(_lockObject);}await Task.Delay(100);}});// 消费者任务var consumer = Task.Run(async () =>{int consumedItems = 0;while (consumedItems < totalItems && !_cancellationTokenSource.Token.IsCancellationRequested){lock (_lockObject){while (queue.Count == 0 && consumedItems < totalItems){Monitor.Wait(_lockObject);}if (queue.Count > 0){int item = queue.Dequeue();consumedItems++;AppendOutputThreadSafe($"消费者消费: {item}");Monitor.PulseAll(_lockObject);}}await Task.Delay(150);}if (!_cancellationTokenSource.Token.IsCancellationRequested){AppendOutputThreadSafe("生产者-消费者演示完成");AppendOutputThreadSafe("");UpdateStatus("生产者-消费者演示完成");}});}// 5. 并行处理演示private void btnParallelProcessing_Click(object sender, EventArgs e){UpdateStatus("并行处理运行中...");AppendOutput("5. 并行处理演示");AppendOutput("---------------");var numbers = Enumerable.Range(1, 10).ToList(); // 减少数量用于演示// 重置进度条Invoke(new Action(() =>{progressBar1.Value = 0;_completedTasks = 0;lblProgress.Text = "任务进度: 0%";}));// 并行处理Task.Run(() =>{AppendOutputThreadSafe("开始并行处理...");Parallel.ForEach(numbers, new ParallelOptions { MaxDegreeOfParallelism = 3 }, number =>{if (_cancellationTokenSource.Token.IsCancellationRequested)return;ProcessNumber(number);// 更新进度int completed = Interlocked.Increment(ref _completedTasks);int progress = completed * 100 / numbers.Count;UpdateProgressBarThreadSafe(progress);UpdateStatus($"并行处理进度: {progress}%");});if (!_cancellationTokenSource.Token.IsCancellationRequested){AppendOutputThreadSafe("并行处理完成");AppendOutputThreadSafe("");UpdateStatus("并行处理完成");}});}private void ProcessNumber(int number){// 模拟一些工作Thread.Sleep(500);AppendOutputThreadSafe($"处理数字: {number} (线程: {Thread.CurrentThread.ManagedThreadId})");}// 6. 取消任务演示private void btnCancelTasks_Click(object sender, EventArgs e){AppendOutput("取消所有任务...");_cancellationTokenSource.Cancel();_cancellationTokenSource = new CancellationTokenSource(); // 创建新的取消令牌UpdateStatus("已发送取消请求");// 重新启用按钮btnBackgroundTask.Enabled = true;}// 7. 清空输出private void btnClear_Click(object sender, EventArgs e){txtOutput.Clear();UpdateStatus("输出已清空");}// 线程安全的输出方法private void AppendOutput(string text){if (txtOutput.InvokeRequired){txtOutput.Invoke(new Action<string>(AppendOutput), text);}else{txtOutput.AppendText(text + Environment.NewLine);txtOutput.ScrollToCaret();}}private void AppendOutputThreadSafe(string text){AppendOutput(text);}private void UpdateProgressBarThreadSafe(int value){if (progressBar1.InvokeRequired){progressBar1.Invoke(new Action<int>(UpdateProgressBarThreadSafe), value);}else{progressBar1.Value = Math.Min(value, progressBar1.Maximum);lblProgress.Text = $"任务进度: {value}%";}}private void UpdateStatus(string status){if (lblStatus.InvokeRequired){lblStatus.Invoke(new Action<string>(UpdateStatus), status);}else{lblStatus.Text = status;}}private void Form1_FormClosing(object sender, FormClosingEventArgs e){_cancellationTokenSource?.Cancel();}}
}
三、效果演示
按下并行处理,多线程运行,同时进度条开始更新。