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问题。

相关推荐
nVisual6 分钟前
数据中心机柜负载均衡与三相相位监控方案
运维·网络·负载均衡·数据中心布线·综合布线管理软件
对讲机数码科普22 分钟前
黑龙江应急救援单工通信保障方案设计与实战应用
大数据·网络·人工智能
Helen_cai22 分钟前
EntryAbility 全局初始化 + 网络请求 HttpUtil 完整源码
网络·华为·harmonyos
驭渊的小故事1 小时前
UDP 和 TCP 网络知识和“Udp协议的回声服务器详细剖析”(5000字详细解析回升服务器的点点滴滴)(网络编程01)
网络
砚凝霜1 小时前
软考网络工程师|第 2 章 信道延迟、传输介质、数据编码、数字调制、PCM 完整备考笔记
网络·笔记·pcm
czhc11400756631 小时前
722:零侵入;DBG;
c#
aixingkong9211 小时前
Atlas 950 1024卡SuperPoD推测分析
网络·人工智能·硬件架构·硬件工程
码农学院4 小时前
基于运维监控体系的网络品牌推广方案:从架构设计到技术实现
运维·网络
-银雾鸢尾-10 小时前
C#中的StringBuilder相关方法
开发语言·c#
-银雾鸢尾-11 小时前
C#中结构体与类的区别;抽象类与接口的区别
开发语言·c#