我上课了。它有一个做很多工作的方法。我希望在它完成工作时不要让程序挂起。我理解yield
会为我做这件事。
void Start() {
DoWork(10,10);
}
void DoWork (int x, int y) {
for (int i=0; i < x; i++) {
for (int j=0; j < y; j++) {
// Stuff
}
}
}
如果我像这样添加yield
void Start() {
DoWork(10, 10);
}
IEnumerable DoWork (int x, int y) {
for (int i=0; i < x; i++) {
for (int j=0; j < y; j++) {
// Stuff
}
Debug.Log (1);
yield return null;
}
}
没有任何工作完成,除此之外我根本看不到任何日志声明。
我如何yield
我的代码以便程序不会冻结?
答案 0 :(得分:2)
您需要使用StartCoroutine方法:
void Start() {
StartCoroutine(DoWork(10, 10));
}
IEnumerator DoWork (int x, int y) {
// (A)
yield return null;
// (B)
for (int i=0; i < x; i++) {
for (int j=0; j < y; j++) {
// Stuff
}
Debug.Log (1);
yield return null;
// (C)
}
}
你的代码是逐段执行的,其中步骤的分隔符是yield运算符,即当Framework第一次调用MoveNext()时 - 代码(A)将被执行,当它第二次调用MoveNext()时 - 代码(B)将被执行,然后是代码(C),依此类推。
答案 1 :(得分:2)
这是Unity3D引擎,因此您的协程需要返回IEnumerator才有效:
void Start() {
StartCoroutine(DoWork(10, 10));
}
IEnumerator DoWork (int x, int y) {
for (int i=0; i < x; i++) {
for (int j=0; j < y; j++) {
// Stuff
}
Debug.Log (1);
yield return null;
}
}
这绝不是多线程的。它的运行方式就像Update和LateUpdate之间每帧更新一次,除非您使用
yield return new WaitForEndOfFrame();
然后推迟到渲染过程之后。它的作用是创建一个Coroutine类型的新对象,并将其放在调用MonoBehaviour协程栈上。
这可以作为执行某些重复操作的方法,但在达到yield时总是返回主程序。然后它会在下一帧回收。
答案 2 :(得分:1)
当您添加yield
语句时,编译器实际上会生成一个私有类,它充当实现IEnumerable
的状态机。因此,除非你枚举方法的结果,否则不会调用从原始方法中包含的代码 - 在你的示例中,你将丢弃返回值,因此不会发生任何事情。
答案 3 :(得分:0)
Yield
关键字用于C#中的延迟加载/计算支持。
尝试做:
var result = DoWork().ToList();
这会强制评估DoWork()方法,您将看到正在进行记录。
答案 4 :(得分:0)
Unity中的C#yield就像C#yield一样。 Unity不以任何方式影响这一点。
yield
是一个关键字,用于允许对一组返回值进行枚举。
IEnumerator<int> MyEnumerationMethod()
{
yield return 5;
yield return 1;
yield return 9;
yield return 4;
}
void UserMethod1()
{
foreach (int retVal in MyEnumerationMethod())
Console.Write(retVal + ", ");
// this does print out 5, 1, 9, 4,
}
void UserMethod2()
{
IEnumerator<int> myEnumerator = MyEnumerationMethod();
while (myEnumerator.MoveNext())
Console.Write(myEnumerator.Current + ", ");
// this does print out 5, 1, 9, 4,
}
UserMethod1()和UserMethod2()几乎相同。 UserMethod1()只是UserMethod2()的C#语法糖版本。
Unity使用此语言功能来实现Coroutines:
当您致电StartCoroutine()
并将其传递给IEnumerator
时,Unity会存储此枚举器并首次调用MoveNext()
。这将导致MyEnumerationMethod()
被调用并执行到第一个yield return
。此时,MoveNext()
返回,并且可以通过查看枚举器的Current
属性来检索第一个结果(5)。
现在,Unity会定期检查Current
属性,并根据其值决定是否再次呼叫MoveNext()
。 Current
的值可能是WaitForEndOfFrame
的实例,WWW
的实例或其他任何内容,并且根据时间,MoveNext()
被调用。
再次调用MoveNext()
后,MyEnumerationMethod()
的执行将在上次中断时继续执行,并执行直到执行下一个yield return
。等等。
这就是屈服,而团结中的Coroutines。