等待所有请求继续

Ed *_*iro 0 c# webrequest unity-game-engine async-await

请问,这段代码可以异步完成吗?我有问题,因为在代码可以继续之前,所有请求都必须终止,我看到了一些关于如何等待一个孤立的请求,但后来我无法使用循环,我一直在尝试解决这个问题,如果有人可以的话帮帮我吧,太好了。

StartCoroutine(GetTexture());    

IEnumerator GetTexture() {

    for (int i = 0; i < 10; i++)
    {
        string url = string.Format("https://galinha.webhost.com/img/{0}.jpg", words[i]);
        UnityWebRequest www = UnityWebRequestTexture.GetTexture(url);
        yield return www.SendWebRequest();

        if(www.isNetworkError || www.isHttpError) {
            selectionSprites.Add(sprites[i]);
        }
        else {
            Texture2D myTexture = ((DownloadHandlerTexture)www.downloadHandler).texture;
            Sprite spriteFromWeb = Sprite.Create(myTexture, new Rect(0, 0, myTexture.width, myTexture.height), new Vector2(0, 0));
            selectionSprites.Add(spriteFromWeb);  
        }

    }//for
Run Code Online (Sandbox Code Playgroud)

der*_*ugo 6

这段代码可以异步完成吗?

请注意,这async是一个关键字,在这里有点误导。当然你可以做网络请求等,async但代码会完全不同,因为大多数 Unity API 不能在线程上使用......

协程永远不会async但仍然在主线程中运行,就像它们是临时Update方法一样。事实上,MoveNext对 Coroutines的调用是在Update.


并行等待多个 WebRequests

所以我猜你更喜欢的是什么

可以并行等待这些请求吗?

我能想象到的最简单的解决方案是存储所有UnityWebRequestAsyncOperations(SendWebRequest在数组中返回的内容,yield直到它们都isDone像例如

using System.Linq;

...

IEnumerator GetTexture() 
{
    var requests = new List<UnityWebRequestAsyncOperation>(10);

    // Start all requests
    for (var i = 0; i < 10; i++)
    {
        var url = string.Format("https://galinha.webhost.com/img/{0}.jpg", words[i]);
        var www = UnityWebRequestTexture.GetTexture(url);

        // starts the request but doesn't wait for it for now
        requests.Add(www.SendWebRequest());
    }

    // Now wait for all requests parallel
    yield return new WaitUntil(() => AllRequestsDone(requests));

    // Now evaluate all results
    HandleAllRequestsWhenFinished(requests);

    foreach(var request in requests)
    {
        request.Dispose();
    }
}

private void HandleAllRequestsWhenFinished(List<UnityWebRequestAsyncOperation> requests)
{
    for(var i = 0; i < 10; i++)
    {
        var www = requests[i].webRequest;
        if(www.isNetworkError || www.isHttpError) 
        {
            selectionSprites.Add(sprites[i]);
        }
        else 
        {
            Texture2D myTexture = ((DownloadHandlerTexture)www.downloadHandler).texture;
            Sprite spriteFromWeb = Sprite.Create(myTexture, new Rect(0, 0, myTexture.width, myTexture.height), new Vector2(0, 0));
            selectionSprites.Add(spriteFromWeb);  
        }
    }
}

private bool AllRequestsDone(List<UnityWebRequestAsyncOperation> requests)
{
    // A little Linq magic
    // returns true if All requests are done
    return requests.All(r => r.isDone);

    // Ofcourse you could do the same using a loop
    //foreach(var r in requests)
    //{
    //    if(!r.isDone) return false;
    //}
    //return true;
} 
Run Code Online (Sandbox Code Playgroud)

为了完整性:WaitUntilLinqAll