gpt4 book ai didi

c# - 嵌套协程生成的代码是什么

转载 作者:太空宇宙 更新时间:2023-11-03 23:22:51 24 4
gpt4 key购买 nike

编辑原始问题以详细说明:我正在使用 unity 协程来执行一些繁重的操作。 Unity 是一个游戏引擎,代码在框架内运行。如果一个操作是密集型的,它必须在协程中完成,否则一个框架需要很长时间才能完成。这里协程方法是DoTasks。如果您不熟悉 unity 引擎,它们类似于迭代器。

首先,我必须说这些代码按预期工作。问题在于堆分配。也就是说,我将解释代码的作用。当调用 Init 时,它会启动协程并进入 DoTask,然后进入 foreach 以迭代 currentTask.Execute() 然后进入obj.CreateCellGosTask 进行迭代。现在我们遇到第一个 yield return,foreach 链将结果返回到初始协程(即 StartCoroutine(DoTasks()) ),我们完成了框架。在下一帧,代码在执行的最后一行之后继续在链中。这是行为并且工作正常。

public class TaskScheduler : MonoBehaviour
{
private static volatile Task currentTask;
public void Init(){
StartCoroutine(DoTasks()); //Starts the coroutine
}
private IEnumerator DoTasks()
{
while(true){
foreach (object b in currentTask.Execute())
{
yield return b;
//Do something
}
}
}



public class Task
{
private Cell cell;
public IEnumerable Execute()
{
foreach (object b in cell.CreateCellGosTask()){
yield return b;
// Do something
}
}

yield 返回是零重要性。在所有嵌套迭代器中,它 yield 返回 null。

问题是关于堆分配的。由于编译器生成实现 IEnumerable 的隐藏(我认为),因此代码会产生垃圾。不幸的是,垃圾收集在统一中是一件大事。

最终目标是将foreach链中的堆分配归零(StartCoroutine并不重要)。所以问题是编译器生成什么代码以及它如何创建Enumerable和Enumerator类?我的意思是 DoTasksExecute 的确切生成代码。然后我可以键入完全相同的代码并创建并返回一个 struct 而不是一个类。

最佳答案

(您可能更愿意跳到下面我用大写字母的简短解释!)

我可能误解了你的意思,但是,

1) 协程与线程完全无关。

(Unity 根本不使用线程。如果你需要创建一个线程(比如用于处理),你需要使用线程管理器(有很多可用的,或者自己编写)......但它与协程。)

2) 协程没有返回值。您只需 yield return null 跳过一个帧或在完成时中断..

一些笔记,

http://answers.unity3d.com/answers/966469/view.html http://answers.unity3d.com/answers/1119978/view.html

那是关于“你如何不止一次调用协程的‘结果’”的讨论,这与你的问题有点相关。 (当我自己问这个 ... https://stackoverflow.com/a/34550206/294884 ... 我当然没有意识到!)

我希望这对您有所帮助!

终于到了

4) 您不能以任何有意义的方式嵌套协程。

您只是在“启动另一个新协程”。你知道?您指的是要么只是“等到”一个完成运行另一个,要么“继续”并一次启动几个。

Google 对此进行了 100 多次讨论.. http://answers.unity3d.com/questions/14081/nested-coroutines.htmlhttp://answers.unity3d.com/answers/515074/view.html

您不能以任何方式有意义地“嵌套协程”。

假设您有一张厨房 table ,上面放着秒表。您启动并运行秒表。如果出于某种原因你想要,你可以启动并运行其中的许多。 (其中一些“可能会启动其他”自己,或者可能会从其他地方启动。)

但是没有“嵌套”它们的概念,它们只是跑在那里的秒表。

不要忘记,您所说的只是“它是将运行每一帧的代码”——仅此而已。 (与 Update() 完全一样。)

再一次 ----- 我觉得您实际上追求的是在 Unity 中进行线程化,这可以通过小心实现。例子---

http://answers.unity3d.com/answers/443604/view.html

实际上,您有点不想与整个框架系统或协同程序有任何关系,听起来您需要一个线程,也许需要进行数学计算。


绝对清楚......

只是重复同样的观点,

public class TaskScheduler : MonoBehaviour

注意协程非常简单

与“任务”或“线程”完全没有联系

“协程”无非就是这样:

每帧都运行一些东西的方法。

就是这样。如您所知,游戏引擎环境为您提供了“每一帧...”概念运行循环。

假设无论出于何种原因(比如.. 移动物体,动画怪物)你想“每一帧”做一些事情。在 Unity 中有两种方法可以访问该功能。

(1) 只需使用 Unity 为您提供的 Update() 准函数:

Update()
{
if ( moveTheDinosaur )
{
// code here will run every frame,
// frames are beautifully managed by Unity
{

(2) 只用协程:

launch coroutine showDinosaur
coroutine showDinosaur()
{
while(true)
{
// code here will run every frame,
// frames are beautifully managed by Unity
yield return null;
// the formulaic line "yield return null"
// indicates to the MonoBehaviour engine that's
// the end of your processing this frame;
// (Implementation details are unknown to us
// and irrelevant)
}
}

请注意 - 事实上 - 如果您是一位经验丰富的程序员,一旦您使用 Unity 超过一天,您就会意识到“Update()”这件事通常来说是完全愚蠢的,您倾向于只使用自己的协程每帧做一些事情。 (当然,“Update()”仅用于快速演示或测试代码时的任何其他内容。)

再次重申,协程与“任务”或“线程”没有任何联系——我想,当然我可能是错的——这就是你想要的.协程只是您访问 Unity 中的“框架系统”的方式。对于统一线程,请查看许多可用的线程池助手类型脚本或系统之一,它们很方便。

关于c# - 嵌套协程生成的代码是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34783651/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com