开源 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() 初始化界面

创建取消令牌源实例

设置初始状态

  1. 核心演示方法

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:线程间通信

缓冲区管理:防止队列溢出

协调生产者和消费者的速度差异

  1. 线程安全辅助方法

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;
    }
}

作用:提供用户友好的状态反馈。

  1. 任务管理方法

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);
        }

        #endregion

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

三、效果演示

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

相关推荐
问道飞鱼3 小时前
【服务器知识】HTTP 请求头信息及其用途详细说明
运维·服务器·nginx·http·http头信息
周杰伦fans11 小时前
C# 23种设计模式详解与示例
开发语言·设计模式·c#
xb113212 小时前
C#——方法的定义、调用与调试
开发语言·c#
code bean13 小时前
【C#】以 BlockingCollection 为核心的多相机 YOLO 检测任务处理框架
c#
专业软件系统开发13 小时前
多盘资源搜索转存系统源码v3.6 全开源版
开源·多盘资源搜索·网盘搜索源码
xiejava101814 小时前
开源安全管理平台wazuh-安装与配置
安全·开源
时光追逐者14 小时前
一款专门为 WPF 打造的开源 Office 风格用户界面控件库
ui·开源·c#·.net·wpf
算家计算16 小时前
DeepSeek发布新模型!采用全新稀疏注意力架构设计,与国产芯片协同优化
人工智能·开源·deepseek
-可乐加冰吗17 小时前
SuperMap iObjects .NET 11i 二次开发(十五)—— 类型转换之面转点
visualstudio·c#·.net