How to tell what queue a completionHandler executes on?
Asked Answered
L

3

7

Looking at the documentation for URLSession.dataTask it's clear this function is called asynchronously but there's no mention of whether the completionHandler returns to the main thread, the thread which called it or remains on the thread the dataTaskOperation was performed on.

Is there a general convention to expect here?

  let task = URLSession.shared().dataTask(with: request) {
        //What Thread are we on here?
    }
Littell answered 23/2, 2018 at 16:9 Comment(4)
According to the docs: "The completion handler to call when the load request is complete. This handler is executed on the delegate queue." developer.apple.com/documentation/foundation/urlsession/… [edit: sorry, you already included the link to the docs]Cupp
@Cupp true... but it doesn't say anywhere what type of queue that is when you're using URLSession.shared. Nor does it way what type of queue is created when you don't pass one into the init method. It just says that it will create a queue to perform the handlers.Aggravation
It doesn't matter which queue/thread it runs on. If you don't know (i.e. you haven't set the delegate queue), just use a dispatch async call in the completion handler to force the queue you want.Determine
@Determine I do that at present but my code would be less indented and more readable if it turns out I don't need to do that.Littell
B
9

From the documentation of the completionHandler parameter of URLSession dataTask:

This handler is executed on the delegate queue.

So the next question is, what is the delegate queue? That all depends on how the URLSession was setup. You are using the shared session which sets a nil delegate queue. The documentation for the queue parameter of the init method states:

If nil, the session creates a serial operation queue for performing all delegate method calls and completion handler calls.

So the code you posted results in the completion handler being called on a background serial queue.

Brumfield answered 23/2, 2018 at 16:20 Comment(1)
Oh! "Creates a queue" i.e. "doesn't use the main queue". I was looking for something more explicit than that in the documentation.Aggravation
A
1

URLSession

In the documentation it says...

This handler is executed on the delegate queue.

And looking at the delegate queue...

All delegate method calls and completion handlers related to the session are performed on this queue. The session object keeps a strong reference to this queue until your app exits or the session object is deallocated. If you do not invalidate the session, your app leaks memory until it exits.

Note

This queue must be set at object creation time and may not be changed.

And looking at the init method...

It doesn't actually say anything about what type of queue is used...

Hmm...

As pointed out by @rmaddy a serial queue is created by the session so that would run on a background thread.

Conventions

As for conventions... there isn't really one.

If you write your own there are things to consider... is the completion likely going to update the UI? Will the completion do lots of data processing etc... and you can decide from there.

Aggravation answered 23/2, 2018 at 16:19 Comment(0)
T
0

As suggested by @rmaddy, it's indeed run on a separate queue. It seems to be labelled: com.apple.NSURLSession-delegate

The experiment:

import Foundation

func currentQueueName() -> String? {
    String(cString: __dispatch_queue_get_label(nil), encoding: .utf8)
}

let dispatchQueue = DispatchQueue(label: "my-queue", qos: .userInteractive)
dispatchQueue.async {
    print(currentQueueName()!) // output: my-queue
    URLSession.shared.dataTask(with: URL(string:"https://www.google.com")!) { _,_,_ in
        print(currentQueueName()!) // output: com.apple.NSURLSession-delegate
    }.resume()
}
Trudge answered 13/7, 2021 at 11:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.