- Home /
Co-routine killed after yield return UnityWebRequest.SendWebRequest
In my application several co-routines are downloading files in parallel, and there is a chance that they can try do download the same file to the same path - resulting into a collision and an access exception. I've tried solving this by using a static collection private static List<string> filesBeingDownloadedNow = new List<string>();
which holds filePath for files which are currently being downloaded.
It looks like this:
private static List<string> filesBeingDownloadedNow = new List<string>();
private IEnumerator DoDownloadCoroutine(string url, string filePath)
{
filesBeingDownloadedNow.Add(filePath);
var webRequest = new UnityWebRequest(url)
{
method = UnityWebRequest.kHttpVerbGET,
downloadHandler = new DownloadHandlerFile(filePath)
{
removeFileOnAbort = true
}
};
yield return webRequest.SendWebRequest();
if (webRequest.isNetworkError || webRequest.isHttpError)
{
// do something if the file failed to download
}
else
{
// do something with the downloaded file
}
filesBeingDownloadedNow.Remove(filePath);
}
and elsewhere:
if (filesBeingDownloadedNow.Contains(filePath))
{
// start another coroutine which simply waits until
// filesBeingDownloadedNow doesn't contain filePath anymore
// and then works with the downloaded file
// as if this coroutine downloaded it itself
}
else
{
StartCoroutine(DoDownloadCoroutine(url, filePath));
}
Now, this works perfectly fine, but there is a rare case where the gameObject on which this coroutine runs can be destroyed before the file download coroutine finishes. So, yield return webRequest.SendWebRequest();
will be the last thing ever called here, and neither success nor failure can be checked, and filesBeingDownloadedNow.Remove(filePath);
is never reached.
I tested this, and it seems that UnityWebRequest.SendWebRequest
still downloads the file in full - however, it's unclear when it will end or if the file gets downloaded successfully at all. It simply "gets lost in the ether".
I could simply trying doing exception handling around File.Open or whatever other things I'd like to do with the downloaded file (and actually should do that in any case). However, UnityWebRequest doesn't allow handling exceptions since it's called with yield return
.
Even if before calling webRequest.SendWebRequest();
I check if the file already exists with if (File.Existst(filePath))
, that doesn't help if 2 different UnityWebRequests try downloading the same file at almost the same time. It can be that the 1st UnityWebRequest has only just connected to the server and hasn't created a file at filePath yet, and the 2nd coroutine will see that the file doesn't exist and assume that no one is downloading it right now, and still attempt a download with webRequest.SendWebRequest();
, resulting in a collision and an exception which I can't handle.
So basically, there is a combination of factors:
Co-routines can be silently killed at any moment without anything like "finally" to do clean up or anything before it's killed
UnityWebRequest.SendWebRequest doesn't allow handling exceptions (?)
Delay before the downloaded file actually appears at the location makes it impossible to check if a file is already being downloaded
Frankly, I also really dislike the static list here, but it seems that since files are a global resource anyway, making it non-static solves nothing. UnityWebRequest.SendWebRequest will keep downloading the file on its own no matter what I do with that list.
there is a rare case where the gameObject on which this coroutine runs can be destroyed before the file download coroutine finishes
This feels like a design flaw to me. Is there any reason you can't you put your downloading functionality into a single persistent object? I think it'd simplify a lot of things.
Thanks, yes I thought of that as well since it looks like the only solution. Just wasn't sure if I maybe misunderstand something about how coroutines or UnityWebRequest work.
Your answer
Follow this Question
Related Questions
Coroutine not executing code after yield return <>.sendWebRequest 0 Answers
Designing a batch controller for multiple web service requests 1 Answer
multiple webrequests, one exception causes next to time out, rest are fine 0 Answers
Unity keep crashing when loading scene from a couritne (Unity 5.x) 1 Answer
How do I do something after multiple coroutines finish? 1 Answer