VS中是否存在Unity3D中的WaitUntil()等价物



在Unity3D中,有一些协程可以在其中调用WaitUntil(),直到语句变为true,例如当字符串不为空时。

string str="";
yield return new WaitUntil(()=>str!="");

我发现它非常有用,并希望在VS中使用它。

我创建了两个类,比如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更适合这份工作。当然,我可能错了!

PS。我尽量避免像while(Str=="");这样的东西,因为它处理量很大!

即使它在不同的线程上运行,它仍然会占用不必要的内存和处理能力。

因此,如果可能的话,我想完全推迟,直到满足继续的条件。

非常感谢你的帮助!

非常感谢!

我不是Unity专家,但据我所知,Unity在游戏的每一帧都调用Update()函数。同样基于文档,它看起来像这样(Unity(:

yield return WaitUntil(() => condition);

与此相同(纯C#(:

while (!condition)
yield return null;

在没有详细说明强大的yield关键字的情况下,这两个关键字都返回一个IEnumerator。每次你";移动到下一个";迭代器的值,则执行函数并返回下一个值。只要有要返回的值,包括nullMoveNext()就会返回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}");
}
}
}

EDIT
要准确使用您的示例,您可以将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不必担心或知道。

最新更新