[英]Is there an equivalent of WaitUntil() from Unity3D in VS?
在 Unity3D 中,您可以在协程中调用WaitUntil()
直到语句变为真,例如当字符串不为空时。
string str="";
yield return new WaitUntil(()=>str!="");
我发现它非常有用,并希望在 VS 中使用它。
我设法通过创建 2 个类来做到这一点,比如 A 和 B,
class A
{
public B b;
public void Set(B bb)
{
b = bb;
b.Str = "Test";
b.ARE.Set();
}
}
class B
{
public string Str="";
public AutoResetEvent ARE = new AutoResetEvent(false);
public B()
{
Thread t = new Thread(Run);
t.Start();
}
private void Run()
{
ARE.WaitOne();
MessageBox.Show(String.Format($"The new string is {Str}");
}
}
public static void Main()
{
A a = new A();
B b = new B();
a.Set(b);
}
如您所见,B 的执行依赖于 A 设置 B 的AutoResetEvent
。
有没有办法让B自己处理?
我对Task.WhenAll
和其他主题做了一些研究,但我真的不知道如何使用它,最后,我认为AutoResetEvent
更适合这项工作。 但当然,我可能是错的!
附注。 我试图避免像while(Str=="");
这样的事情while(Str=="");
因为它处理繁重!
即使它运行在不同的线程上,它仍然会占用不必要的内存和处理能力。
所以如果可能的话,我想完全推迟它,直到满足继续的条件。
非常感谢您的帮助!
非常感激!
我不是 Unity 专家,但据我所知,Unity 在游戏的每一帧都会调用Update()
函数。 同样基于文档,它看起来像这样(Unity):
yield return WaitUntil(() => condition);
与此相同(纯C#):
while (!condition)
yield return null;
没有详细说明强大的yield
关键字,它们都返回一个IEnumerator
。 每次您“移动 [到] 下一个”迭代器的值时,都会执行该函数并返回下一个值。 只要有要返回的值,包括null
, MoveNext()
就会返回true
。
基本上, WaitUntil()
似乎是某种 Unity 方言,用于在纯 C# 中等效。 我怀疑StartCoroutine()
类的东西是一种类似的启动线程的机制(不确定这个)。
这是一个试图解释发生了什么的工作程序:
using System;
using System.Collections;
using System.Threading;
namespace ConsoleTest
{
public class Program
{
private static int frameCounter;
public class B
{
public string MyString { get; set; }
public IEnumerator Run()
{
while (string.IsNullOrEmpty(MyString))
{
Console.WriteLine("Nothing here yet..."); // This is printed every time MoveNext() is called on the iterator.
yield return null;
}
// MyString is not null anymore: print this.
// This is also the end of the enumerator: no more values will be returned.
Console.WriteLine("MyString has been set after we " + MyString);
}
}
public static void Main()
{
// This simulates Unity's engine by generating one frame every 500ms.
var frameTimer = new Timer(_ => UpdateFrameCounter(), null, 0, 500);
// Creates an instance of B and get the enumerator by calling Run():
var b = new B();
var enumerator = b.Run();
// As long as there are values being returned (by yield), stay in this loop.
// Here, this means basically "as long as b.MyString is null or empty".
while (enumerator.MoveNext())
{
// Demo purposes: block main thread for 1sec.
Thread.Sleep(1000);
// At frame 10, set the value of b.MyString
if (frameCounter == 10)
{
b.MyString = "reached 10 frames.";
}
}
// We'll reach this when there are no more values to be returned, i.e. enumerator.MoveNext() == false.
// Stop the timer and quit.
frameTimer.Change(Timeout.Infinite, Timeout.Infinite);
Console.WriteLine("Press any key to quit...");
Console.ReadKey();
}
public static void UpdateFrameCounter()
{
// Update frame counter (-> Unity engine).
Console.WriteLine($"Frame counter: {++frameCounter}");
}
}
}
编辑
要准确使用您的示例,您可以将b.Str
设置为属性,然后在那里重置事件:
// In class B:
private string str = string.Empty; // private field
public string Str // public property
{
get => str;
set
{
str = value;
ARE.Set(); // this is called each time b.Str value is set
}
}
这样,当 A 或任何其他类设置 b.Str 的值时, ARE
将自动设置,而 A 不必担心或知道它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.