D.C.
D.C.

Reputation: 15588

What queue should delegate code run on

Suppose you have an object that does some work internally on a private dispatch queue (think thread for those not familiar with GCD). This object notifies its delegate at various times throughout the work its doing. It is a bad idea to call the delegate methods from the private queue the code is currently running on, or should they be called on a more well-known queue? If the latter, what queue? It seems like main queue may not always be what you want.

Option A

dispatch_async(private_queue, ^{
    // Do some work...
    [self.delegate tellItWorkWasDone:self];
});

Option B

dispatch_async(private_queue, ^{
    // Do some work...
    dispatch_sync(dispatch_get_main_queue(), ^{
        [self.delegate tellItWorkWasDone:self];
    });
});

Option A has the benefit that its simple, but the drawback that whoever implements the delegate method will be running code on a queue they really shouldn't be on. Option B is probably safer, but main_queue is just an example; how should the two really decide on what queue they should use?

Thanks

Upvotes: 3

Views: 1476

Answers (4)

Vernadsky
Vernadsky

Reputation: 11

You could also add a delegateQueue argument to the init of your class. That way you can give the consumer of the class full control on which queue to fire the delegate calls on.

The other answers are correct in saying that UI actions should take place on the main queue. It would be a waste though if your class queues the delegate call on the main queue when it's not necessary for the consuming class.

Upvotes: 1

Catfish_Man
Catfish_Man

Reputation: 41801

I would suggest an option C, actually: have a dedicated queue for delegate callbacks unless the delegate's activity must be completed before your class can continue, in which case use option A.

If UI needs updating, the delegate can dispatch to the main queue itself, don't force that on it.

Upvotes: 2

svena
svena

Reputation: 2779

I believe it is a matter of contract between you and your API user. Whichever approach you choose, be explicit about it because the user of your API has to know it.

The significance of the decision, as @andreagiavatto correctly pointed out, is that updating UI must be done on the main thread. And if you have not explicitly stated whether your callbacks or completion handlers are always queued on main thread, the user of your API must always take the extra step to wrap it in another dispatch_async() to main thread, if it's UI related.

If you are the only user of your API, being explicit and being consistent helps to avoid silly mistakes.

Here's how I have chosen to do it:

  1. The general rule is that my delegate callbacks are invoked inline with the asynchronously running code, as your option A.
  2. If the purpose of delegate callbacks are 99% about providing UI feedback, I queue them on the main thread, as your option B and document it both on header file and docs.

Upvotes: 1

andreag
andreag

Reputation: 881

If your delegate is responsible for updating the UI then you should definitely use Option B because Apple says

Important: Not all UIKit classes are thread safe. Be sure to check the documentation before performing drawing-related operations on threads other than your app’s main thread.

If this is not the case, Option A should be fine as well.

Upvotes: 1

Related Questions