NSURLSessionDownloadTask resumes automatically all

2019-02-19 18:39发布

问题:

I have requirement to download files in serial order. Currently I am able to do that while app is in foreground.

Following is the logic I have used.

  1. Create all tasks for downloading.

  2. Resume one at a time and as the current finishes resume the next one from URLSession:task:didCompleteWithError:.

This logic is working while app is in foreground but once app started to run in background(By crashing) and we again run the app before download finishes all the tasks state has been changed to resume and all are downloading at the same time.

Is this the expected behaviour or anything I am missing to order this in serial in background mode too?

Edit: I checked by creating download task one by one. After finishing the first task create next inside setTaskDidCompleteBlock and so on. It only completes the first task and after that session crashed while task created inside setTaskDidCompleteBlock (This happens only when running in background mode, for foreground its working fine).

Here is my crash log screen shots:

and

Any help would be appreciated.

回答1:

If you absolutely need to run these requests sequentially, I would suggest not instantiating all of these tasks up front, but rather instantiate them one at a time, only instantiating the next one upon the completion of the prior one.

But we must recognize that you pay a significant performance penalty for running the requests sequentially. (And this problem will be magnified when using background sessions.) If at all possible, see if you can change your requests to run concurrently. Clearly, if you need the output of one in order to create the request for another, you're stuck (or at least until your refactor the server code), but that's clearly not the issue here (because you created all of the requests up front). If you're doing this sequential request process for artificial reasons (e.g., the code is populating an array and you want that in order), then you might want to redesign the implementation to remove this artificial constraint.



回答2:

I have seen this happen too. If you create a downloadTask while the app is in the foreground but do not call resume(), it will not start — however, it will start automatically when the app is backgrounded.

The solution is to explicitly call suspend() on each downloadTask when you create it. Then, when you are ready to start downloading it, call resume().

Apparently a newly created downloadTask is neither suspended nor resumed. Its initial state is not .Running, but when the app is backgrounded it is shifted into .Running because it hasn't been explicitly suspended. This is suprising behavior; I don't know why the background session daemon works this way.