协程是在Unity3D一个新线程? [英] Is coroutine a new thread in Unity3D?
问题描述
我感到困惑和好奇如何协同程序(在Unity3D也许是其他地方)的工作。协同程序是一个新的线程? Unity的文档他们说:
一个协同程序是可以暂停其执行(收益率),直到给定YieldInstruction完成的功能。
块引用>
使用UnityEngine; System.Collections中使用
;
公共类例如:MonoBehaviour {
无效的start(){
打印(启动+选定了time.time);
StartCoroutine(WaitAndPrint(2.0F));
打印(WaitAndPrint结束前+选定了time.time);
}
IEnumerator的WaitAndPrint(浮动WAITTIME){
收益回报新WaitForSeconds(WAITTIME);
打印(WaitAndPrint+选定了time.time);
}
}
我对这个例子中的许多问题:
<醇>
在上面的例子中,该线是协程?为
WaitAndPrint()
协程?为WaitForSeconds()
协程
在这一行:<?code>收益回报新WaitForSeconds(WAITTIME); ,为什么这两个
收益
和收益
存在?我团结文档中读取的说:yield语句是一种特殊的回报,即保证该功能将继续从它被称为下一次产量语句后线。如果收益
是一个特殊的收益
,是什么收益
操作在这里?
为什么我们必须返回一个
的IEnumerator
?
确实
StartCoroutine
启动一个新线程?
多少倍有
WaitAndPrint()
被称为在上面的例子?难道收益回报新WaitForSeconds(WAITTIME);
真的回来了?如果是的话,我猜WaitAndPrint()
在上面的代码中调用两次。我猜StartCoroutine()
打电话WaitAndPrint()
多次。但是,我看到另一团结文档,上面写着:协同程序的执行可以在任何时候使用yield语句被暂停。当协程恢复产量的返回值规定。这些话让我觉得WaitAndPrint()
居然还没有回来;它只是被暂停;它正在等待WaitForSeconds()
返回。如果是这种情况,那么在上面的代码WaitAndPrint()
被称为只有一次,而StartCoroutine
只是负责启动功能,多次不调用它。
解决方案协同程序是用于模拟各种由异步/地等待着.net4.5,但在早期版本(C#> = V2.0)支持的功能极其强大的技术。
微软CCR (取读)也使用(使用?)这个方法。
让我们一件事的出路。
收益
单独无效,总是后跟收益
或破
。
想想一个标准的IEnumerator(不产生流量控制消息)。
的IEnumerator YieldMeSomeStuff()
{
收益率你好;
Console.WriteLine(富!);
收益率的世界;
}
现在:
IEnumerator的E = YieldMeSomeStuff();
,而(e.MoveNext())
{
Console.WriteLine(e.Current);
}
什么是输出?
你好
富!
世界
注意怎么样,我们称之为第二次
的MoveNext
,前枚举取得了世界的一些代码运行枚举器内。这意味着,在枚举器,我们可以直到遇到一个收益回报率
语句编写一个执行代码,然后简单地暂停,直到有人叫MoveNext的
(轻易地与所有国家/变量整齐捕获,因此,我们可以拿起我们不放过)。一个的MoveNext
呼叫后,的收益回报率
语句后的代码下位可以运行,直到另一个达到产量的回报
。因此,我们现在可以控制在收益回报率
语句之间的代码的执行的MoveNext
来电来枚举。
现在,说的不是屈服字符串,我们的调查员都得到一个消息,以
$ B线的MoveNext
的来电者说,的请流连X(WAITTIME)秒,你打电话之前的MoveNext
再次的。来电者将被写入理解各种消息。这些消息会一直沿的请等待某某的MoveNext
前再打电话来发生的
$ b现在我们已经暂停和重新启动需要得到满足,才可以进行其他条件代码的有力手段,而无需编写功能到另一种方法,像做异步的东西,而协同程序。如果没有协同程序,你的力量,以绕过一个可怕的异步状态对象,你需要手动组装一个方法的结束和另一个经过一番异步的东西出发)之间的捕捉状态。协同程序消除了这一点,因为范围将被保留(由编译器魔法),这样你的局部变量,坚持在长住异步的东西。
$得心应手b $ b
StartCoroutine
只是开始的全过程。它调用的MoveNext
的枚举...一些代码在枚举...枚举器产生一个控制消息,通知在StartCoroutine代码运行
时,的MoveNext
再打电话。这不一定在一个新线程发生,但可以在多线程方案,因为我们可以称之为的MoveNext
来自不同的线程控制那里的工作就完成了。I am confused and curious about how coroutines (in Unity3D and perhaps other places) work. Is coroutine a new thread? Unity's documentation they said:
A coroutine is a function that can suspend its execution (yield) until the given YieldInstruction finishes.
And they have C# examples here:
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); } }
I have many questions about this example:
In the example above, which line is the coroutine? Is
WaitAndPrint()
a coroutine? IsWaitForSeconds()
a coroutine?In this line:
yield return new WaitForSeconds(waitTime);
, why bothyield
andreturn
are present? I read in Unity documentation that "The yield statement is a special kind of return, that ensures that the function will continue from the line after the yield statement next time it is called." Ifyield
is a specialreturn
, what isreturn
doing here?Why do we have to return an
IEnumerator
?Does
StartCoroutine
start a new thread?How many times has
WaitAndPrint()
been called in the above example? Didyield return new WaitForSeconds(waitTime);
really returned? If yes then I guessWaitAndPrint()
was called twice in the above code. And I guessStartCoroutine()
was callingWaitAndPrint()
multiple times. However, I saw another Unity documentation that says: "The execution of a coroutine can be paused at any point using the yield statement. The yield return value specifies when the coroutine is resumed." These words make me feel thatWaitAndPrint()
actually has not returned; it was merely paused; it was waiting forWaitForSeconds()
to return. If this is the case, then in the above codeWaitAndPrint()
was called only once, andStartCoroutine
was just responsible for starting the function, not calling it multiple times.
解决方案Coroutines are an extremely powerful technique used to emulate the kinds of features supported by the async/await in .net4.5, but in earlier versions ( c# >= v2.0 ) .
Microsoft CCR (take a read) also employs (employed?) this approach.
Let's get one thing out of the way.
yield
alone is not valid and is always followed by eitherreturn
orbreak
.Think about a standard IEnumerator (that doesn't yield flow control messages).
IEnumerator YieldMeSomeStuff() { yield "hello"; Console.WriteLine("foo!"); yield "world"; }
Now:
IEnumerator e = YieldMeSomeStuff(); while(e.MoveNext()) { Console.WriteLine(e.Current); }
What's the output?
hello foo! worldNotice how, the second time we called
MoveNext
, before the Enumerator yielded "world" some code ran within the Enumerator. What this means is that in the Enumerator, we can write code that executes until it hits ayield return
statement, then simply pauses until someone callsMoveNext
(handily with all state/variables neatly captured, so we can pick up where we left off). After aMoveNext
call, the next bit of code after theyield return
statement can run until anotheryield return
is reached. So we can now control the execution of the code between theyield return
statements with theMoveNext
call to the Enumerator.Now, say instead of yielding strings, our Enumerator were to yield a message that says to the caller of
MoveNext
, "please hang around for x (waitTime) seconds before you callMoveNext
again". The caller is written to "understand" a variety of messages. These messages will always be along the lines of "please wait for such and such to happen before callingMoveNext
again".Now we have a powerful means of pausing and restarting code that requires other conditions to be met before it can proceed, without having to write that functionality into another method, like doing async stuff without coroutines. Without coroutines, you're forces to pass around a horrible async state object that you would need to manually assemble to capture state between the end of one method and the starting of another after some async stuff). Coroutines eliminate this because scope is preserved (by compiler magic), so your local variables persist over long lived async stuff.
StartCoroutine
simply starts the whole process. It callsMoveNext
on the Enumerator... some code runs in the Enumerator... The enumerator yields a control message, which informs the code inStartCoroutine
when to callMoveNext
again. This need not happen in a new Thread, but can be handy in multithreaded scenarios because we can callMoveNext
from different threads and control where the work is done.这篇关于协程是在Unity3D一个新线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!