Art*_*rtS 3 c# unity-game-engine
我有一个协程如下:
IEnumerator CountingCoroutine()
{
while (true)
{
DoSomething();
yield return new WaitForSeconds(1);
}
}
Run Code Online (Sandbox Code Playgroud)
我需要在其中调用一些异步函数。如果我按如下方式编写,编译器会抱怨:
async IEnumerator CountingCoroutine()
{
while (true)
{
DoSomething();
await foo();
yield return new WaitForSeconds(1);
}
}
Run Code Online (Sandbox Code Playgroud)
每秒调用一些异步函数的正确等待时间是多少?PS我可以放弃整个协程函数并使用带有计时机制的更新,并将更新函数标记为异步。但我不确定它是否安全或推荐。
根据 @derHugo 的建议解决方案:
IEnumerator CountingCoroutine()
{
while (true)
{
DoSomething();
var task = Task.Run(foo);
yield return new WaitUntil(()=> task.IsCompleted);
yield return new WaitForSeconds(1);
}
}
Run Code Online (Sandbox Code Playgroud)
你可以使用Task.IsCompleted
喜欢
private IEnumerator CountingCoroutine()
{
while (true)
{
DoSomething();
var task = Task.Run(foo);
yield return new WaitUntil(()=> task.IsCompleted);
}
}
Run Code Online (Sandbox Code Playgroud)
一旦之前的任务完成,它就会开始运行新的任务。
您可以扩展它,以便最早大约每秒开始一个新任务,或者最晚在前一个任务在一秒后完成时开始,例如
private IEnumerator CountingCoroutine()
{
var stopWatch = new StopWatch();
while (true)
{
DoSomething();
stopWatch.Restart();
var task = Task.Run(foo);
yield return new WaitUntil(()=> task.IsCompleted);
var delay = Mathf.Max(0, 1 - stopWatch.ElapsedMilliseconds * 1000);
// Delays between 1 frame and 1 second .. but only the rest that foo didn't eat up
yield return new WaitForSeconds(delay);
// or you could with a bit more calculation effort also
// even avoid the one skipped frame completely
if(!Mathf.Approximately(0, delay)) yield return new WaitForSeconds(delay);
}
}
Run Code Online (Sandbox Code Playgroud)
或者,如果您不关心完成情况,只想像每秒所说的那样调用它,那么只需这样做
private IEnumerator CountingCoroutine()
{
while (true)
{
DoSomething();
Task.Run(foo);
yield return new WaitForSeconds(1);
}
}
Run Code Online (Sandbox Code Playgroud)
但请注意,这样您将失去所有控制,并且永远不会知道其中一项任务是否以及何时完成,并且可能会导致多个并发任务运行/失败等
作为替代方案,您也可以反过来使用Asyncoroutine之类的东西。不过,您可能必须注意后台线程上的事物。
更新
现在我宁愿建议尝试一下UniTask(也可以通过OpenUPM获得)!它是一个轻量级的异步任务实现,还提供无缝的异步 <-> Unity 主线程集成。
| 归档时间: |
|
| 查看次数: |
9732 次 |
| 最近记录: |