C#异步编程

工作之后在很多项目中遇到了async相关的编程知识,这一块笔者了解甚少,属于是实践之后又回来学习理论,有一些小的心得分享给大家同时也巩固自身的学习

异步

对于如下一段程序

{

A();

B();

}

同步方式:运行A -> 等待运行A -> 等待A运行完了运行B

异步方式:运行A -> 等待运行A -> 在等待的过程中去运行CDEFG... ->A运行完了运行B额

一、async 和 await

异步方法使用 async修饰。其返回值类型为Task或者void,其中Task表示异步操作。

等待一个异步操作的完成使用await ,await只能在异步方法中使用。

await A; =》如果A还没有完成,那么就暂停程序的顺序执行,并将控制权返回给调用者,调用者去干别的事,直到异步操作完成。

当异步操作完成之后,await会自动恢复后续代码执行。

二、Task

Task代表一个异步操作,相当于是一个将要完成任务的句柄的存在。

为什么异步方法返回Task

同步方法可以直接返回结果,因为计算已经完成,而异步方法返回时,计算还没完成,没法直接给Int,此时此刻需要一个容器来表示这个操作还在进行中,将来存放计算结果,将来存放异常信息,提供等待,回调,取消等能力。而这个容器就是Task

c# 复制代码
同步方法
public int GetResult(){
	Thread.Sleep(1000); //等待一秒
	return 42; //一秒后返回
异步方法
public Task<int> GetResultAsync(){
	await Task.Delay(1000) //不阻塞线程,先立马返回给你一个Task,这1秒你先去干别的活
	return 42; //1秒后结果就放到task中
}

Task结构

概念上,task内部大概是这样

c# 复制代码
class Task<int>{
	int _result;
	bool _isCompleted;
	Exception _error;

public void Wait(){}

public int Result{get{...}}
	
}

三、并发调用

并发调用就是等待多个异步任务它们全部完成的方法。

主要是靠 Task.WhenAll 和 Task.WhenAny这俩兄弟来完成。

  • Task.WhenAll => 是C#中并发执行多个任务并等待它们全部完成的方法。
  • Task.WhenAny => 是C#中并发执行多个任务并等待其中任何一个任务完成的方法。

它们都接受一个Task数组作为参数。

四、取消令牌Cancellation Token

在异步操作中,可能会遇到需要取消任务的情况,C#提供了CancellationToken来支持取消任务的机制,通过传递取消令牌,可以在异步方法中处理取消请求,提高程序的灵活性和响应性。

而Cancellation Token 是一种协作机制,操作自己决定何时检查,如何退出。

C# 复制代码
// 1. 创建 CancellationTokenSource
using var cts = new CancellationTokenSource();

// 2. 获取 Token 传给要支持取消的操作
CancellationToken token = cts.Token;

// 3. 在异步/后台操作中检查取消
Task.Run(() => DoWork(token), token);  // 注意同时传入 token 给 Task.Run

// 4. 在适当的时候发出取消请求
cts.Cancel();

void DoWork(CancellationToken token)
{
    for (int i = 0; i < 100; i++)
    {
        // 方式一:检查 IsCancellationRequested(推荐非频繁操作)
        if (token.IsCancellationRequested)
        {
            // 清理资源后退出
            Console.WriteLine("检测到取消,退出");
            return;
        }
        
        // 方式二:调用 ThrowIfCancellationRequested(推荐用于需要抛出异常终止的地方)
        token.ThrowIfCancellationRequested();
        
        // 执行实际工作...
        Thread.Sleep(100);
    }
}

public async Task DownloadAsync(string url, CancellationToken token)
{
     var client = new HttpClient();
    // 支持取消的异步方法可以传入 token
    var response = await client.GetAsync(url, token);
    var data = await response.Content.ReadAsStringAsync();
    
    // 也可以在自己的循环中检查
    await foreach (var item in ProcessStreamAsync(token).WithCancellation(token))
    {
        // ...
    }
}

令牌底层结构

c# 复制代码
// 1. CancellationTokenSource - 信号的"发射器"
public class CancellationTokenSource : IDisposable
{
    private CancellationTokenCallback _callbacks;  // 回调链表
    private int _state;  // 0: None, 1: Cancelled, 2: Disposed
    
    public void Cancel()  // 发出取消信号
    public CancellationToken Token { get; }  // 获取"接收器"
    public static CancellationTokenSource CreateLinkedTokenSource(...)
}

// 2. CancellationToken - 信号的"接收器"(结构体,零开销)
public struct CancellationToken
{
    private CancellationTokenSource _source;  // 引用源
    public bool IsCancellationRequested { get; }  // 检查是否被取消
    public void ThrowIfCancellationRequested()  // 取消时抛异常
    public CancellationTokenRegistration Register(Action callback)  // 注册回调
}

// 3. OperationCanceledException - 约定的"终止信号"
public class OperationCanceledException : Exception
{
    public CancellationToken? CancellationToken { get; }
}

五、UniTask-Unity中的异步

UniTask是Unity版本的异步编程,比原生Task更快,更适合Unity中的异步操作。

没有UniTask的时候,我们往往使用协助程。

而UniTask帮助解决没有返回值,不能try-catch,处理GC问题。

相关推荐
2401_873479401 小时前
如何用IP离线库阻断挖矿和僵尸网络?DNS层防护实战指南
网络·网络协议·tcp/ip·ip
MXsoft6181 小时前
**配置自动备份与变更告警:杜绝“黑变更”风险**
网络·数据库
BomanGe12 小时前
NSK紧凑型FA系列精密滚珠丝杠技术解析
运维·服务器·网络·经验分享·规格说明书
rcms152702692182 小时前
MSM030C-0300-NN-M0-CG0伺服电机
网络
去码头整点薯条982 小时前
网络实验报告9
运维·服务器·网络
AI科技星2 小时前
《数术工坊:非欧射影录》类型:硬核光影·几何本源
c语言·开发语言·网络·量子计算·agi
Yiyaoshujuku3 小时前
化合物数据集API接口(数据结构及样例)
java·网络·数据结构
影寂ldy3 小时前
C# 三大内置委托(Action / Func / Predicate)+ Lambda
c++·算法·c#
MXsoft6184 小时前
**从设备到业务:如何用业务视角管理IT?**
网络