Wait for all requests to continue

会有一股神秘感。 提交于 2019-12-11 17:00:03

问题


Please, can this code be done async? I have problems because all requests must be terminated before the code can continue, I saw something about how wait an isolated request, but then i couldn't use the loop, I've been trying to solve this for a while, if anyone can help me it would e great.

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

回答1:


can this code be done async?

note that async is a keyword and a bit misleading here. Ofcourse you can do web requests etc async but the code would be completely different since most of the Unity API can't be used on threads...

Coroutines are never async but still run in the main thread like if they were temporary Update methods. In fact the MoveNext call for Coroutines is done right after the Update.


Waiting for multiple WebRequests parallel

So I guess what you rather ment is

can these requests be awaited parallel?

Esiest solution I can imagine where you wouldn't have to change your code structure too much would be to store all UnityWebRequestAsyncOperations (what is returned by SendWebRequest in an array and yield until all of them are isDone like e.g.

using System.Linq;

...

IEnumerator GetTexture() 
{
    var requests = new 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[i] = www.SendWebRequest();
    }

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

    // Now evaluate all results
    HandleAllRequestsWhenFinished(requests);
}

private void HandleAllRequestsWhenFinished(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(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;
} 

For completeness: WaitUntil and Linq All




回答2:


I Tried put the StarCoroutine into the loop for, but dont work, it even worked on the one hand, cause the program waited untill the last Startcoroutine, but dont waited the last to complete, and also it ran all Webrequest kinda at the same time, not respecting the order in the end. I could have tried to put the Inumerator into the loop together with the Coroutine, to see how it would behave, but i dont.

I also tried the script above, using System.Linq and UnityWebRequestAsyncOperation[], but it exhibited similar behavior that my origin script, I still couldn't get that the program wait for all the coroutine.

In the end, i just did the request in a previous scene and load in a static list to use when it was necessary, that way I think the game even works more fluid.

Thanks for all help.



来源:https://stackoverflow.com/questions/58827893/wait-for-all-requests-to-continue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!