目录 不用模板生成的目录怎么这么丑啊
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 所需要执行的话");
}
}
输出结果很意思,这明显不是按照顺序来的
更加证明了这是异步的,记住:代码可以在等待某些任务完成时继续执行其他任务