协程是在Unity3D一个新线程? [英] Is coroutine a new thread in Unity3D?

查看:218
本文介绍了协程是在Unity3D一个新线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我感到困惑和好奇如何协同程序(在Unity3D也许是其他地方)的工作。协同程序是一个新的线程? Unity的文档他们说:




一个协同程序是可以暂停其执行(收益率),直到给定YieldInstruction完成的功能。




和他们有这里的C#示例 的:

 使用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 来电来枚举。



    现在,说的不是屈服字符串,我们的调查员都得到一个消息,以的MoveNext 的来电者说,的请流连X(WAITTIME)秒,你打电话之前的MoveNext 再次的。来电者将被写入理解各种消息。这些消息会一直沿的请等待某某的MoveNext 前再打电话来发生

    $ B线
    $ b

    现在我们已经暂停和重新启动需要得到满足,才可以进行其他条件代码的有力手段,而无需编写功能到另一种方法,像做异步的东西,而协同程序。如果没有协同程序,你的力量,以绕过一个可怕的异步状态对象,你需要手动组装一个方法的结束和另一个经过一番异步的东西出发)之间的捕捉状态。协同程序消除了这一点,因为范围将被保留(由编译器魔法),这样你的局部变量,坚持在长住异步的东西。



    StartCoroutine 只是开始的全过程。它调用的MoveNext 的枚举...一些代码在枚举...枚举器产生一个控制消息,通知在 StartCoroutine代码运行时,的MoveNext 再打电话。这不一定在一个新线程发生,但可以在多线程方案,因为我们可以称之为的MoveNext 来自不同的线程控制那里的工作就完成了。

    $得心应手b $ b

    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:

    1. In the example above, which line is the coroutine? Is WaitAndPrint() a coroutine? Is WaitForSeconds() a coroutine?

    2. In this line: yield return new WaitForSeconds(waitTime);, why both yield and return 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." If yield is a special return, what is return doing here?

    3. Why do we have to return an IEnumerator?

    4. Does StartCoroutine start a new thread?

    5. How many times has WaitAndPrint() been called in the above example? Did yield return new WaitForSeconds(waitTime); really returned? If yes then I guess WaitAndPrint() was called twice in the above code. And I guess StartCoroutine() was calling WaitAndPrint() 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 that WaitAndPrint() actually has not returned; it was merely paused; it was waiting for WaitForSeconds() to return. If this is the case, then in the above code WaitAndPrint() was called only once, and StartCoroutine 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 either return or break.

    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!
    world
    

    Notice 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 a yield return statement, then simply pauses until someone calls MoveNext (handily with all state/variables neatly captured, so we can pick up where we left off). After a MoveNext call, the next bit of code after the yield return statement can run until another yield return is reached. So we can now control the execution of the code between the yield return statements with the MoveNext 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 call MoveNext 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 calling MoveNext 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 calls MoveNext on the Enumerator... some code runs in the Enumerator... The enumerator yields a control message, which informs the code in StartCoroutine when to call MoveNext again. This need not happen in a new Thread, but can be handy in multithreaded scenarios because we can call MoveNext from different threads and control where the work is done.

    这篇关于协程是在Unity3D一个新线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆