unity的异步操作

1.C#提供了两个关键字来实现异步async和await

async 关键字用于声明一个异步方法。该方法内部可以使用 await 关键字来等待异步操作的完成。当方法被标记为 async 时,它隐式地表示该方法可能会包含一个或多个 await 表达式。重要的是要注意,async 方法通常会返回一个 Task 或 Task<T> 类型的对象,其中 T 是方法的返回类型。

await 关键字用于等待一个异步操作的完成。它只能在被 async 修饰的方法内部使用。当遇到 await 表达式时,编译器会自动将方法分成两部分:await 表达式之前的代码会在原始线程上同步执行,而 await 表达式之后的代码会在异步操作完成时,在另一个线程(或从线程池中获取的线程)上继续执行。这个过程是自动的,不需要开发者手动管理线程。

例子:

复制代码
using System;  
using System.IO;  
using System.Threading.Tasks;  
  
class Program  
{  
    static async Task Main(string[] args)  
    {  
        string content = await ReadFileAsync("example.txt");  
        Console.WriteLine(content);  
    }  
  
    static async Task<string> ReadFileAsync(string filePath)  
    {  
        using (StreamReader reader = new StreamReader(filePath))  
        {  
            // 注意:StreamReader 没有直接的异步读取方法,这里为了示例  
            // 我们假设有一个,但在现实中,你可能会使用 File.ReadAllTextAsync 等  
            // 这里使用 Task.Run 来模拟异步操作  
            string content = await Task.Run(() =>  
            {  
                return reader.ReadToEnd();  
            });  
            return content;  
        }  
    }  
}  
  
// 注意:上面的 ReadFileAsync 方法中使用了 Task.Run 来模拟异步操作,  
// 但在实际应用中,读取文件应该使用 File.ReadAllTextAsync 或类似的异步API。
复制代码

2.UniTask

Task的升级版本(第三方弄出来代替Task和协程的方案),0GC的真异步解决方案。

例子:

复制代码
public async UniTask AsyncSetImage(string address)
{
    ZCancelSource.Return(ref cancelSource_);
    cancelSource_ = ZCancelSource.Rent();
    try
    {
        Sprite spr = await ZResLoader.Instance.LoadAssetAsync<Sprite>(address, cancelSource_.CreateToken(), 1000);
        this.sprite = spr;

        ZCancelSource.Return(ref cancelSource_);
    }
}
复制代码

 3.打断操作

unitask提供了CancelTokenSource,但会有GC,所以最好还是自己写一套

ZCancelSource:管理一组CancelToken(uint类型,每次照上一次递增,在0-uint.maxvalue中循环,维护一个dict来标记token是否存在),每个CancelToken对应一个异步逻辑,可以指定打断/取消某一个异步逻辑。

复制代码
private static async UniTask<object> loadAssetAsyncInternal(uint realAddress, uint token)
{
...
    if (ZCancelSource.IsCanceled(token))
    {
        throw new ArgumentException($"[ZResLoader] invaid token on LoadAssetAsync, token={token}");
    }
...

     while (!asset.IsDone && !ZCancelSource.IsCanceled(token))
    {
        await UniTask.Yield();
    }

    if (ZCancelSource.IsCanceled(token))
    {
        asset.Release();
        throw ZCancelSource.CancelException;
    }

    ZCancelSource.ReleaseToken(token);
...
}
复制代码

 

posted @   mc宇少  阅读(277)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2020-09-02 unityGUID(转)
点击右上角即可分享
微信分享提示