C# & Unity 同步/异步编程和多线程什么关系?async/await和coroutine又是什么?

目录 不用模板生成的目录怎么这么丑啊

1.同步?异步?多线程?

2.async/await和coroutine?

证明

单线程中的同步/异步

同

异

多线程中的同步异步

同

异

1.同步?异步?多线程?

首先,你需要知道什么是同步编程,什么是异步编程

同步编程:所有代码按顺序执行,直到当前任务完成后才开始下一个任务

异步编程:代码可以在等待某些任务完成时继续执行其他任务

其次,你需要知道什么是多线程

**多线程:**是一种并发编程技术,允许一个程序同时执行多个线程

好,既然你能明白概念,说明你非常聪明,可以直接上第一个结论了

当然不懂也没关系,先有个印象我会说明为什么

2.async/await和coroutine?

我直接指名加油站,看懂了就行,二者都是异步处理的解决方法

async/await: async/await 用法,看这一篇就够了_async await用法-CSDN博客

coroutine: unity保姆级教程之协同程序_unity 协同程序实现原理-CSDN博客

请看下图结论

证明

单线程中的同步/异步

同

所有代码按顺序执行,直到当前任务完成后才开始下一个任务

举一个我家老太太都会写的例子

cs 复制代码
public class Single : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Func1();
        Func2();
    }

    void Func1()
        {
        Debug.Log("这是函数1 所需要执行的话");
    }
    void Func2() {
        Debug.Log("这是函数2 所需要执行的话");
    }
}

结果,注意时间

就相当于如此

异

代码可以在等待某些任务完成时继续执行其他任务

用协程函数

cs 复制代码
public class Single : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(Wait());
    }
    IEnumerator Wait()
        {
        Func1();
        yield return new WaitForSeconds(1.0f);
        Func2 ();
    }

    void Func1()
        {
        Debug.Log("这是函数1 所需要执行的话");
    }
    void Func2() {
        Debug.Log("这是函数2 所需要执行的话");
    }
}

注意时间

用async/await

cs 复制代码
public class Single : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Wait();
    }
    async void Wait() {
        Func1();
        await Task.Delay(1000); // 等待1秒
        Func2();
    }

结果当然是毫不意外

二者用图解 皆是如此

牢记这句话:代码可以在等待某些任务完成时继续执行其他任务

我可以在这1s打个胶还是什么都行,是不是非常严谨

多线程中的同步异步

同

多线程会遇到一个问题,就是新开的线程是独立的,并不会受到启动顺序的影响

比如:

cs 复制代码
  void Start()
  {
      Thread t1 = new Thread(Func1);
      Thread t2 =new Thread(Func2);
      t1.Start();
      t2.Start();
  }

那么就会出现这种情况:

即:有时候会是func1先执行,有时候会使func2先执行

那么要是使其实现同步的话,就需要加一个小小的类ManualResetEvent 类 (System.Threading) | Microsoft Learn

这样就可以实现,所有代码按顺序执行,直到当前任务完成后才开始下一个任务

cs 复制代码
public class Single : MonoBehaviour
{
    ManualResetEvent resetEvent = new ManualResetEvent(false);
    // Start is called before the first frame update
    void Start()
    {
        Thread t1 = new Thread(Func1);
        Thread t2 =new Thread(Func2);
        t1.Start();
        t2.Start();
    }

    void Func1()
        {
        Debug.Log("这是函数1 所需要执行的话");
        resetEvent.Set();
    }
    void Func2() {
        resetEvent.WaitOne();
        Debug.Log("这是函数2 所需要执行的话"); 
    }
}

另外你需要注意的一个点就是在unity中,其有自己的一个主线程用于执行生命周期函数,图解如下:

异

代码可以在等待某些任务完成时继续执行其他任务

cs 复制代码
public class Single : MonoBehaviour {
    // TaskCompletionSource 用于在异步任务之间传递信号
    private TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();

    async void Start() {
        Task t1= Func1();
        Debug.Log("看看这句话是在哪执行的1");
        Task t2 = Func2();
        Debug.Log("看看这句话是在哪执行的2");
        // 等待两个任务都完成
        await Task.WhenAll(t1, t2);
       
    }

    async Task Func1() {
        Debug.Log("这是函数1 所需要执行的话");

        // 设置 TaskCompletionSource 的结果,通知 Func2 可以继续执行
        tcs.SetResult(true);
    }

    async Task Func2() {
        // 等待 Func1 完成
        await tcs.Task;
        // 延迟一秒
        await Task.Delay(1000);
        Debug.Log("这是函数2 所需要执行的话");
    }
}

这我就不得不多说两句了,在这段代码中unity有自己的主线程,而t1和t2是副线程

当调用t1和t2时,这两个线程会在后台并行执行,而主线程会继续执行后续的代码。主线程和工作线程之间是并行运行的,互不阻塞

协程同理

cs 复制代码
public class Single : MonoBehaviour {
    Thread t1;
    Thread t2;
   void Start() {
        t1 = new Thread(Func1);
        t2 = new Thread(Func2);
        Debug.Log("看看这句话输出在哪里1");
        StartCoroutine(wait());
        Debug.Log("看看这句话输出在哪里2");
    }

    IEnumerator wait()
        { 
    t1.Start();
    yield return new WaitForSeconds(1.0f);
     t2.Start ();
    }
    // 异步方法 Func1
    void Func1() {
        // 输出调试信息
        Debug.Log("这是函数1 所需要执行的话");

    }

    // 异步方法 Func2
    void Func2() {

        Debug.Log("这是函数2 所需要执行的话");
    }
}

输出结果很意思,这明显不是按照顺序来的

更加证明了这是异步的,记住:代码可以在等待某些任务完成时继续执行其他任务

相关推荐
http阿拉丁神猫4 小时前
Go语言入门笔记:从基础到开发环境搭建(二)
开发语言·笔记·golang
不会就选b5 小时前
C++补充部分(一)--lambda 表达式
开发语言·c++
czhc11400756635 小时前
同值短路与单一真值源:属性不是命令,状态只有一个家
c#
Pniubi8 小时前
HashMap的扩容和树化边界
java·开发语言
gCode Teacher 格码致知9 小时前
Pandas教学-17:Series与Dataframe的关系
开发语言·python·pandas
发量惊人的中年网工9 小时前
分公司访问总部ERP慢怎么办?SD-WAN组网的排查与验收要点
服务器·开发语言·php
下页、再停留10 小时前
【C#桌面客户端系列学习-15】生成可视化图表之折线图、柱状图、饼状图
开发语言·c#
ShineWinsu10 小时前
对于JavaScript:操作元素的解析
开发语言·前端·javascript·面试·web·dom·元素
益莱储中国11 小时前
深度解析:RF 实验室从 5G迈向 6G 的过程中保持技术领先与设备升级的路径
开发语言·php
benchmark_cc12 小时前
Python 量化系统如何设计统一的数据访问接口:从策略解耦到数据层架构
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash