[英]Is coroutine a new thread in Unity3D?
關於協同程序 (在Unity3D和其他地方)如何工作,我感到困惑和好奇。 coroutine是新線程嗎? 他們說Unity的文檔 :
協程是一個可以暫停執行(yield)直到給定的YieldInstruction完成的函數。
他們在這里有C#示例:
using UnityEngine;
using System.Collections;
public class example : MonoBehaviour {
void Start() {
print("Starting " + Time.time);
StartCoroutine(WaitAndPrint(2.0F));
print("Before WaitAndPrint Finishes " + Time.time);
}
IEnumerator WaitAndPrint(float waitTime) {
yield return new WaitForSeconds(waitTime);
print("WaitAndPrint " + Time.time);
}
}
我對這個例子有很多疑問:
在上面的例子中,哪一行是協程? 是的WaitAndPrint()
是一個協程嗎? 是WaitForSeconds()
是一個協程嗎?
在這一行中: yield return new WaitForSeconds(waitTime);
,為什么yield
和return
都存在? 我在Unity文檔中讀到“yield語句是一種特殊的返回,它確保函數將在下次調用yield語句后繼續執行。” 如果yield
是一個特殊的return
,那么return
在這里做什么?
為什么我們必須返回IEnumerator
?
StartCoroutine
是否啟動了一個新線程?
在上面的例子中調用了WaitAndPrint()
多少次? yield return new WaitForSeconds(waitTime);
真的回來了? 如果是,那么我猜WaitAndPrint()
在上面的代碼中被調用了兩次。 我猜StartCoroutine()
多次調用WaitAndPrint()
。 但是,我看到另一個Unity文檔說:“可以使用yield語句在任何時候暫停執行協程。yield return value指定何時恢復協程。” 這些話讓我覺得WaitAndPrint()
實際上還沒有返回; 它只是暫停了; 它正在等待WaitForSeconds()
返回。 如果是這種情況,那么在上面的代碼中, WaitAndPrint()
只被調用一次,而StartCoroutine
只負責啟動該函數,而不是多次調用它。
協同程序是一種非常強大的技術,用於模擬.net4.5中async / await支持的各種功能,但在早期版本中(c#> = v2.0)。
Microsoft CCR (讀取)也采用(使用?)這種方法。
讓我們放開一件事。 單獨的yield
無效,並且始終是return
或break
。
想想標准的IEnumerator(它不會產生流控制消息)。
IEnumerator YieldMeSomeStuff()
{
yield "hello";
Console.WriteLine("foo!");
yield "world";
}
現在:
IEnumerator e = YieldMeSomeStuff();
while(e.MoveNext())
{
Console.WriteLine(e.Current);
}
什么輸出?
hello foo! world
請注意,在枚舉器產生“世界”之前,我們第二次調用MoveNext
,在枚舉器中運行了一些代碼。 這意味着在Enumerator中,我們可以編寫執行代碼直到它yield return
語句,然后暫停直到有人調用MoveNext
(輕松地將所有狀態/變量整齊地捕獲,所以我們可以從我們中斷的地方繼續) 。 在MoveNext
調用之后, yield return
語句之后的下一位代碼可以運行,直到達到另一個yield return
。 因此,我們現在可以通過對Enumerator的MoveNext
調用來控制yield return
語句之間的代碼執行。
現在,我們的枚舉器不是產生字符串,而是產生一條消息,告訴MoveNext
的調用者, “請再次調用MoveNext
之前暫停x(waitTime)秒” 。 寫入調用者是為了“理解”各種消息。 這些消息將始終沿着“請等待再次調用MoveNext
之前發生這樣的事情” 。
現在我們有一個強大的暫停和重新啟動代碼的方法,它需要滿足其他條件才能繼續,而不必將該功能寫入另一個方法,比如在沒有協同程序的情況下執行異步操作。 如果沒有協同程序,你就會強行傳遞一個可怕的異步狀態對象,你需要手動組裝以捕獲一個方法結束和另一個異步之后的另一個方法的啟動之間的狀態。 協同程序消除了這種情況,因為范圍被保留(通過編譯器魔術),因此您的本地變量會持久存在於長期存在的異步內容中。
StartCoroutine
只是啟動整個過程。 它在Enumerator上調用MoveNext
...一些代碼在Enumerator中運行...枚舉器產生一條控制消息,它通知StartCoroutine
的代碼何時再次調用MoveNext
。 這不需要在新的Thread中發生,但在多線程場景中可以很方便,因為我們可以從不同的線程調用MoveNext
並控制工作的完成位置。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.