Unity 在内部只是简单地创建一个 IEnumerator 和 yields 每帧直到异步加载任务完成。
你可以例如做类似的事情
public static IEnumerator WaitUntilIsDoneAsync(Action action)
{
var task = task.Run(() => action?.Invoke());
while (!task.IsCompleted)
{
yield return null;
}
}
然后你可以等待一些长时间的异步工作完成,例如
yield return WaitUntilIsDoneAsync(() =>
{
Thread.Sleep(3000);
}
当然,为了使它更有用,您可能更愿意像他们那样实现一个类,您还可以在其中存储任务结果以供以后访问等。
这当然很大程度上取决于您期望返回的类型。
它可以例如看起来像这样。请注意,我不是异步专家,并且从空中抓住这个例子..不知道它是否完全像那样工作,但只是解释在后台或多或少发生了什么。
所以为了yield你只需要anyIEnumerator,它不必通过StartCoroutine启动。
所以你可以通过实现IEnumerator来实现这一点
public class AsyncFileLoadRequest : IEnumerator
{
private readonly object _contentLock = new object();
private Task<string> asyncLoadingTask;
public string File content
{
get
{
lock(_contentLock)
{
return _fileContent;
}
}
}
public AsyncFileLoadRequest(string path)
{
asyncLoadTask = File.ReadAllTextAsync(path);
AwaitTaskAsync();
}
#region IEnumerator implementation
object IEnumerator.Current => null;
public void Reset() { }
public bool MoveNext()
{
// As long as this returns true the coroutine will wait
return !asyncLoadTask.IsCompleted;
}
#endregion IEnumerator implementation
private async void AwaitTaskAsync()
{
lock(_contentLock)
{
_fileContent = await asyncLoadTask;
}
}
}
所以你可以做类似的事情
var request = new AsyncFileLoadRequest(filePath);
yield return request;
var content = request.FileContent;
或者像他们一样使用工厂方法:
public static class FileIOStuff
{
public static AsyncFileLoadRequest LoadFileAsync(string path)
{
return new AsyncFileLoadRequest (path);
}
}
和它一样的称呼
var request = FileIOStuff.LoadFileAsync (filePath);
yield return request;
var content = request.FileContent;