编辑了最初的问题来详细说明:,我正在使用统一协同来执行一些繁重的操作。统一是一个游戏引擎,代码在帧内运行。如果一个操作是密集的,它必须在协同工作,否则它需要很长的时间来完成一个框架。这里的协同线方法是DoTasks。如果您不熟悉统一引擎,则它们类似于迭代器。
首先,我必须说,这些代码的作用就像它们应该做的那样。问题在于堆分配。那就是说我会解释密码是怎么做的。当调用Init时,它启动协同线并进入DoTask,然后在foreach中迭代currentTask.Execute(),然后进入obj.CreateCellGosTask进行迭代。现在,我们遇到的第一个屈服返回,链和返回结果的初始协同线(即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
}
}收益回报是零重要的。在所有嵌套迭代器中,它都会产生返回null。
问题在于堆分配。由于编译器生成隐藏的类实现IEnumerable (我认为),代码会产生垃圾。不幸的是,垃圾收集是一件很重要的事情。
最终目标是在foreach (StartCoroutine不重要)中实现堆分配为零,问题是编译器生成了哪些代码,以及它如何创建可枚举类和枚举器类?我指的是DoTasks和Execute生成的精确代码。然后,我只需键入完全相同的代码,创建并返回一个结构,而不是一个类。
发布于 2016-01-14 12:51:49
(你可能更喜欢跳过我下面大写字母的简短解释!)
我可能误解了你想做的事,但是,
1)协同器与线程完全无关。
(统一根本不使用线程。如果您需要创建一个线程(比如处理),您需要使用线程管理器(有很多可用的线程,或者编写自己的线程管理器).但这与合作关系无关。)
2)协同线没有返回值。你只需要跳过一个框架或者在你完成后中断。
一些笔记,
http://answers.unity3d.com/answers/966469/view.html http://answers.unity3d.com/answers/1119978/view.html
这是一次关于“你如何称呼”‘合作不止一次’的结果的讨论,这与你要问的内容有某种关系。(当我自己问这个. https://stackoverflow.com/a/34550206/294884 .我当然没有意识到!)
我希望这在某种程度上有帮助!
只是最后
4)你不能用任何有意义的方式来嵌套协同。
你只是在“开始另一个新的合作机制”。你知道?你所指的要么只是“等到”一个人运行完另一个,要么是“向前走”,然后一次启动几个。
谷歌对此进行了100多年的讨论http://answers.unity3d.com/questions/14081/nested-coroutines.html或http://answers.unity3d.com/answers/515074/view.html
你不可能以任何方式有意义地“筑巢合作”。
想象一下,你有一张摆着秒表的厨房桌子。你启动并运行秒表。如果出于某种原因,您可以启动和运行其中的许多。(他们中的一些人“可能是自己开始的”,也可能是从哪里开始的。)
但是没有“筑巢”的概念,他们只是在那里跑的秒表。
别忘了,你说的只是“运行每个帧的代码”--仅此而已。(和Update()完全一样。)
我又一次--我有种感觉,你真正想要的是在团结中的线程,这是可以小心实现的。例子
http://answers.unity3d.com/answers/443604/view.html
实际上,你不想和整个框架系统有任何关系,也不想和协作系统有任何关系,听起来你需要一条线--也许是一种数学计算。
绝对清楚.
为了重复同样的观点,
public class TaskScheduler : MonoBehaviour注意,协同机制非常简单
根本没有与“任务”或“线程”的连接。
“协同线”只不过是这样:
一种运行每一个帧的方法。
仅此而已。如你所知,游戏引擎环境给你一个“每一帧.”概念运行循环
不管出于什么原因(比如说. )移动一个物体,动画一个怪物)你想做一些“每一个帧”。在统一中,有两种方法可以获得这种能力。
(1)只需使用联合为您提供的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)
}
}请注意--实际上--如果您是一名经验丰富的程序员,只要使用了一天以上,您就会意识到"Update()“这件事通常是完全愚蠢的,您倾向于使用自己的协同机制来完成每一帧的工作。(当然,"Update()“仅用于测试代码时的快速演示或其他任何操作都很方便。)
再次重申,课程与“任务”或“线程”没有任何关系--我想,,我想,我当然错了, --这就是你想要的。Coroutines是您如何访问统一中的“框架系统”的方法。对于统一的线程处理,请查看许多可用的线程池-助手类型脚本或系统之一,这些脚本或系统非常方便。
https://stackoverflow.com/questions/34783651
复制相似问题