目录 不用模板生成的目录怎么这么丑啊
1.同步?异步?多线程?
2.async/await和coroutine?
证明
单线程中的同步/异步
同
异
多线程中的同步异步
同
异
1.同步?异步?多线程?
首先,你需要知道什么是同步编程,什么是异步编程
同步编程:所有代码按顺序执行,直到当前任务完成后才开始下一个任务
异步编程:代码可以在等待某些任务完成时继续执行其他任务
其次,你需要知道什么是多线程
多线程:是一种并发编程技术,允许一个程序同时执行多个线程
好,既然你能明白概念,说明你非常聪明,可以直接上第一个结论了
当然不懂也没关系,先有个印象我会说明为什么
2.async/await和coroutine?
我直接指名加油站,看懂了就行,二者都是异步处理的解决方法
async/await:async/await 用法,看这一篇就够了_async await用法-CSDN博客
coroutine:unity保姆级教程之协同程序_unity 协同程序实现原理-CSDN博客
请看下图结论
证明
单线程中的同步/异步
同
所有代码按顺序执行,直到当前任务完成后才开始下一个任务
举一个我家老太太都会写的例子
public class Single : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){Func1();Func2();}void Func1(){Debug.Log("这是函数1 所需要执行的话");}void Func2() {Debug.Log("这是函数2 所需要执行的话");}
}
结果,注意时间
就相当于如此
异
代码可以在等待某些任务完成时继续执行其他任务
用协程函数
public class Single : MonoBehaviour
{// Start is called before the first frame updatevoid 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
public class Single : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){Wait();}async void Wait() {Func1();await Task.Delay(1000); // 等待1秒Func2();}
结果当然是毫不意外
二者用图解 皆是如此
牢记这句话:代码可以在等待某些任务完成时继续执行其他任务
我可以在这1s打个胶还是什么都行,是不是非常严谨
多线程中的同步异步
同
多线程会遇到一个问题,就是新开的线程是独立的,并不会受到启动顺序的影响
比如:
void Start(){Thread t1 = new Thread(Func1);Thread t2 =new Thread(Func2);t1.Start();t2.Start();}
那么就会出现这种情况:
即:有时候会是func1先执行,有时候会使func2先执行
那么要是使其实现同步的话,就需要加一个小小的类ManualResetEvent 类 (System.Threading) | Microsoft Learn
这样就可以实现,所有代码按顺序执行,直到当前任务完成后才开始下一个任务
public class Single : MonoBehaviour
{ManualResetEvent resetEvent = new ManualResetEvent(false);// Start is called before the first frame updatevoid 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中,其有自己的一个主线程用于执行生命周期函数,图解如下:
异
代码可以在等待某些任务完成时继续执行其他任务
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时,这两个线程会在后台并行执行,而主线程会继续执行后续的代码。主线程和工作线程之间是并行运行的,互不阻塞
协程同理
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 ();}// 异步方法 Func1void Func1() {// 输出调试信息Debug.Log("这是函数1 所需要执行的话");}// 异步方法 Func2void Func2() {Debug.Log("这是函数2 所需要执行的话");}
}
输出结果很意思,这明显不是按照顺序来的
更加证明了这是异步的,记住:代码可以在等待某些任务完成时继续执行其他任务