C#中的多线程案例

使用Task写一个进度条

cs 复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
​
namespace _5.任务
{
    public partial class Form1 : Form
    {
       
        Task task = null;
        // 取消的标识符,专门用来管理Task。CancellationTokenSource对象可以生成CancellationToken
        // CancellationTokenSource对象还可以取消任务
        CancellationTokenSource cts;
        bool isPause = false;  // 是否暂停
        public Form1()
        {
            InitializeComponent();
            // 实例化取消任务的标识
            cts = new CancellationTokenSource();
            // 实例化任务(创建一个分线程)
            task = new Task(new Action<object>(UpdateProgressBar), 0, cts.Token);
        }
​
        private void UpdateProgressBar(object state)
        {
            while (!cts.IsCancellationRequested && !isPause)
            {
                task.Wait(100);
                Invoke(new Action(() =>
                {
                    state = (int)state + 1;
                    if ((int)state <= 100)
                        progressBar1.Value = (int)state;
                    else
                        cts.Cancel();  // 取消任务后,会影响IsCancellationRequested属性
                }));
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            task.Start();
        }
​
        private void button2_Click(object sender, EventArgs e)
        {
            isPause = true;
        }
​
        private void button3_Click(object sender, EventArgs e)
        {
            isPause = false;
            cts = new CancellationTokenSource();
            task = new Task(new Action<object>(UpdateProgressBar), this.progressBar1.Value, cts.Token);
            task.Start();
        }
​
        private void button4_Click(object sender, EventArgs e)
        {
            isPause = true;
            cts.Cancel();
        }
    }
}
​

CancellationTokenSource怎么使用

CancellationTokenSource 是.NET中用于异步编程的一个类,它允许你创建一个 CancellationToken,这个令牌可以被传递给异步操作,以便在需要时请求取消操作。以下是 CancellationTokenSource 的基本用法:

创建 CancellationTokenSource

cs 复制代码
CancellationTokenSource cts = new CancellationTokenSource();

获取 CancellationToken

CancellationTokenSource 实例中获取 CancellationToken,然后将它传递给需要支持取消的异步操作。

cs 复制代码
CancellationToken token = cts.Token;

传递给异步操作

CancellationToken 作为参数传递给支持取消的异步方法。

cs 复制代码
await SomeAsyncOperationAsync(token);

请求取消

当你需要取消操作时,调用 CancellationTokenSourceCancel 方法。

cs 复制代码
cts.Cancel();

处理取消

在异步方法中,检查 CancellationToken 是否被触发,并在需要时处理取消逻辑。

cs 复制代码
public async Task SomeAsyncOperationAsync(CancellationToken cancellationToken)
{
    try
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            // 执行一些工作
​
            // 定期检查取消请求
            cancellationToken.ThrowIfCancellationRequested();
​
            // 模拟工作延迟
            await Task.Delay(1000);
        }
    }
    catch (OperationCanceledException)
    {
        // 处理取消操作
        Console.WriteLine("Operation was canceled.");
    }
}

完整示例

cs 复制代码
class Program
{
    static async Task Main(string[] args)
    {
        CancellationTokenSource cts = new CancellationTokenSource();
        CancellationToken token = cts.Token;
​
        // 启动异步操作
        Task asyncOperation = SomeAsyncOperationAsync(token);
​
        // 假设5秒后用户请求取消
        await Task.Delay(5000);
        cts.Cancel();
​
        try
        {
            // 等待异步操作完成或抛出异常
            await asyncOperation;
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("The operation was canceled.");
        }
    }
​
    static async Task SomeAsyncOperationAsync(CancellationToken cancellationToken)
    {
        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine($"Working... {i}");
            await Task.Delay(1000, cancellationToken);
​
            if (cancellationToken.IsCancellationRequested)
            {
                Console.WriteLine("Cancellation was requested.");
                throw new OperationCanceledException(cancellationToken);
            }
        }
    }
}

SomeAsyncOperationAsync 方法执行一些工作,并定期检查是否收到了取消请求。如果在5秒后调用了 cts.Cancel(),那么 CancellationTokenSource 会发出取消请求,并且异步操作将捕获 OperationCanceledException 异常来处理取消。

使用 CancellationTokenSourceCancellationToken 提供了一种优雅的方式来请求和响应取消操作,使异步编程更加灵活和健壮。

使用Task写一个进度条

cs 复制代码
using System;
using System.Threading;
using System.Windows.Forms;
​
namespace _2.Thread课堂练习
{
    public partial class Form1 : Form
    {
        Thread t = null; // 线程实例
        bool isCancel = false; // 取消标识
        public Form1()
        {
            InitializeComponent();
​
            t = new Thread(UpdateProgressBar);
            this.button2.Enabled = false;
            this.button3.Enabled = false;
            this.button4.Enabled = false;
        }
​
        private void UpdateProgressBar(object step)
        {
            while (!isCancel && t != null && Convert.ToInt32(step) < 100)
            {
                Thread.Sleep(100);
                step = Convert.ToInt32(step) + 1;
​
                if (Convert.ToInt32(step) <= 100)
                {
                    Invoke(new Action(() =>
                    {
                        progressBar1.Value = Convert.ToInt32(step);
                    }));
                }
                else
                {
                    isCancel = true;
                }
            }
        }
​
        private void button1_Click(object sender, EventArgs e)
        {
            t?.Start(0);
            this.button1.Enabled = false;
            this.button2.Enabled = true;
            this.button4.Enabled = true;
        }
​
        private void button2_Click(object sender, EventArgs e)
        {
            t?.Suspend();
            this.button2.Enabled = false;
            this.button3.Enabled = true;
        }
​
        private void button3_Click(object sender, EventArgs e)
        {
            t?.Resume();
            this.button2.Enabled = true;
            this.button3.Enabled = false;
            this.button4.Enabled = true;
        }
​
        private void button4_Click(object sender, EventArgs e)
        {
            isCancel = true;
            t?.Abort();
            this.button1.Enabled = true;
            this.button2.Enabled = false;
            this.button3.Enabled = false;
            this.button4.Enabled = false;
            t = new Thread(UpdateProgressBar);
            progressBar1.Value = 0;
            isCancel = false;
        }
​
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            isCancel = true;
            t?.Abort();
        }
​
        private void Form1_Load(object sender, EventArgs e)
        {
​
        }
    }
}
复制代码
相关推荐
Traced back5 小时前
怎么用 Modbus 让两个设备互相通信**,包含硬件接线、协议原理、读写步骤,以及 C# 实操示例。
开发语言·c#
一个帅气昵称啊6 小时前
基于.NET AgentFramework开发OpenClaw智能体框架
人工智能·自然语言处理·c#·.net·openclaw
唐青枫7 小时前
C#.NET SpinLock 深入解析:自旋锁原理、使用边界与性能取舍
c#·.net
CSharp精选营14 小时前
.NET对象转JSON,到底有几种方式?
c#·json·.net·newtonsoft·对象转换·utf8json
bcbobo21cn15 小时前
C#引用类型学习
开发语言·c#·值类型·引用类型
天下无敌笨笨熊15 小时前
C#异步开发探微
开发语言·c#
mudtools16 小时前
存储那么贵,何不白嫖飞书云文件空间
前端框架·c#·.net
我是唐青枫16 小时前
C#.NET SignalR + Redis Backplane 深入解析:多节点部署与跨实例消息同步
c#·.net
星河Cynthia17 小时前
WPF基于resx资源文件的多语言实现
c#·wpf