Coroutine doesn't terminate with the callback.

I want to return a string as the return value of the coroutine, but even when calling the callback, the process doesn’t get interrupted. Is this because I’m writing my code incorrectly? Can you provide any guidance?
Thank you !!

    private IEnumerator UploadImageToCloud(string image_dir, Action<string> callback)
    {
        string imageUrl = "";

        byte[] bytes = File.ReadAllBytes(dir)
            ;
        Texture2D texture = new Texture2D(2, 2);
        texture.LoadImage(bytes);

        if (texture != null)
        {
            int width = texture.width;
            int height = texture.height;

// I got the correct size here.
            Debug.Log($"Size : {width} / {height}");

            if (width!=TARGET_SKIN_WIDTH || height!=TARGET_SKIN_HEIGHT)
            {
                Debug.Log("brefore_callback");
                callback(imageUrl);
                Debug.Log("after_callback");

// I got both of "brefore" and "after" _callback logs.
// I want to return "", if the texture size does't match the target size.
            }
        }
        else
        {
            callback(imageUrl);
        }
  
       byte[] bytes = File.ReadAllBytes(dir);

        yield return StartCoroutine(DoingPutRequest(bytes,  x => imageUrl = x));
 
        callback(imageUrl);
}

Generally, you don’t want to “return” anything from a Coroutine. The whole point is that the Coroutine will continue to run on future frames, so there’s nobody left in the first frame to receive your final results.

You are mixing two forms of starting a Coroutine (DoingPutRequest) from within another Coroutine (UploadImageToCloud). You should choose one or the other of these forms:

StartCoroutine(DoingPutRequest(...));
This will start another coroutine along with the first one. Both run in parallel until they finish independently.

yield return DoingPutRequest(...);
This will make the outer coroutine wait for the inner coroutine to complete before continuing.

If you need the results from a long operation, you should be using some form of async/await scheme, instead of Coroutines.

1 Like

I’ve been avoiding Unitask because it seemed difficult to handle, but it might be time to start studying.
Thank you.

I’m confused what your actual problem is. Strangely you call your callback at 3 different places but the first 2 calls would pass an empty string to the coroutine. You said:

Do you mean you want to stop the coroutine when you call your callback? If that’s the case you have to put a yield break; after your callback call. When you call your callback it’s just an ordinary method call. When the callback has finished, the coroutine would continue unless you break out of it. How / from where do you actually call / start your coroutine? And how does your callback look like?

ps: This piece of code:

 x => imageUrl = x

is actually redundant. You could simply pass in your “callback” instead. You create a closure that essentially will provide you a method with the same signature as your callback (so it just gets a single string argument) but you route it through your local imageUrl string just to pass it to your callback. So you can simply do:

yield return DoingPutRequest(bytes,  callback);

So your inner coroutine DoingPutRequest would directly call your callback when it has the necessary data.

Bunny83
Thank you for the response!
I had always thought that a coroutine would be interrupted as soon as callback() was called , like ‘yield break’ you said.
This might be the cause of the issue.
I might have to check all the code I’ve written so far…