问题
在做Unity3D开发时,在整合UnityEngine的异步方法(协程)同其它Framework(如.Net API、WinRT API)的异步方法(async)给我造成了困扰,因为异步的实现的方式不同。在一个方法中等待一个协程返回使用yield return
关键字,并且需要该方法的返回值为IEnumerator;而在一个方法中等待一个async方法返回使用await
关键字,并且需要该方法声明为async方法且返回值必须为void、Task或Task<T>。然而同一个方法中只能有一个返回值,所以看起来无法在同一个方法中同时等待协程和线程。
解决
但其实可以利用Task.IsCompleted
字段来替换await的异步等待方式,在方法中返回一个WaitUtil
对象,即可将线程的异步等待包装为协程的异步等待。例如现在有如下两个异步方法,分别实现自线程和协程:
public async Task<string> ReadAsync(string path) {
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) {
using (StreamReader sw = new StreamReader(fs, Encoding.UTF8)) {
return await sw.ReadToEndAsync();
}
}
}
public IEnumerator LoadResourceAsync(string path) {
yield return Resources.LoadAsync<GameObject>(path);
}
若现在需要实现一个方法,异步等待ReadAsync的结果,并将结果作为参数传递给LoadResourceAsync,则可以这样写:
public IEnumerator TestAsync() {
Task<string> task = ReadAsync("xxx");
yield return new WaitUntil(() => {
return task.IsCompleted;
});
string result = task.Result;
yield return LoadResourceAsync(result);
Debug.Log("执行完成");
}
然后在MonoBehaviour中进行调用
StartCoroutine(TestAsync());
如有错误欢迎指正交流!