当前位置: 首页 > news >正文

开源 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();}}
}

三、效果演示

按下并行处理,多线程运行,同时进度条开始更新。

http://www.dtcms.com/a/423137.html

相关文章:

  • 大学生网站建设策划书响应式网站用什么开发的
  • 交换机可以做网站跳转吗wordpress 目录样式
  • 第2章 三个小工具的编写(1)
  • 生态系统NPP及碳源、碳汇模拟实践技术应用
  • 【Rust GUI开发入门】编写一个本地音乐播放器(3. UI与后台线程通信)
  • P11013 「ALFR Round 4」C 粉碎 题解
  • 跨境商城网站建设公司做小程序要多少钱
  • scratch绘制帽子花 2025年6月中国电子学会图形化编程 少儿编程 scratch编程等级考试三级真题和答案解析
  • 特色专业建设展示网站北京seo培训
  • 网络原理-HTTP补充1
  • 做外贸相关的网站全面的vi设计公司
  • 如何构建高效 AI 智能体
  • 9.25训练赛+Codeforces1054 (Div. 3)
  • 老Java项目访问提示orcale 19c ORA-01017: 用户名/口令无效; 登录被拒绝
  • 目标检测:yolov7算法在RK3588上部署
  • Maya Python: 安装pymel
  • 全景网站开发待遇南宁logo设计公司
  • 北京工商局网站怎么做增资网易代理暴雪
  • 制造行业订单全生命周期管理数仓项目实战
  • 《深度学习入门:基于Python的理论与实现》第7章 卷积神经网络笔记
  • 网络游戏编程 - Socket 技术以及应用 - 上 -《了解游戏网络基础知识》
  • 珠海建网站的网络公司网站名称格式
  • 舆情观察类文章写作指南与新浪舆情通应用
  • C语言——深入理解函数声明定义和调用访问
  • 网站开发大约多少钱制作一个网站的步骤是什么
  • RabbitMQ (一)简单模式
  • 阿里巴巴 Java 开发手册 v1.2.0
  • Leetcode+Java+单调栈
  • Word和WPS文字如何从特定的页开始编号(页码)?
  • EDSR模型