0

I've made an NSOperation subclass with a start method containing a call to a method which has a completion block. The completion block contains code which marks the operation as finished (KVO). That block seems to typically be executed on the main thread (rather than my NSOperationQueue's background thread).

What I'm seeing is that the operation doesn't appear to ever get marked as finished, and I assume this is because of the threading issue. Is there some way I can get the KVO calls to occur on the correct thread, and thus allow my operation to terminate properly?

The method with the completion block is 3rd party code, so I'd prefer not to have to alter it.

EDIT: Here's the relevant code.

-(void)start
{
    [self willChangeValueForKey:@"isExecuting"];
    _isExecuting = YES;
    [self didChangeValueForKey:@"isExecuting"];
    NSData *mutableData = [NSData thisIsWhereMyDataIsCreated];

    [self.peripheral writeData:mutableData characteristicUUID:[CBUUID transmitCharacteristicUUID] serviceUUID:[CBUUID serviceUUID] completion:^(CBCharacteristic * _Nullable characteristic, NSError * _Nullable error) {
        [self markAsFinished];
    }];
}

-(void)markAsFinished
{
    NSLog(@"Finishing op...");
    [self willChangeValueForKey:@"isExecuting"];
    [self willChangeValueForKey:@"isFinished"];

    _isExecuting = NO;
    _isFinished = YES;

    [self didChangeValueForKey:@"isExecuting"];
    [self didChangeValueForKey:@"isFinished"];

    self.onComplete();
}

And it's the markAsFinished: method that's being called on the main thread, via the completion block for the writeData... method.

Patrick
  • 1,629
  • 5
  • 23
  • 44
Darren Black
  • 1,030
  • 1
  • 9
  • 28
  • Is this your issue?: http://stackoverflow.com/a/10423127/653513 – Rok Jarc May 31 '16 at 10:13
  • @rokjarc No it isn't... I'm already sending the KVO notifications manually. – Darren Black May 31 '16 at 10:16
  • 1
    Code? code code code. – Avi May 31 '16 at 10:17
  • @Avi: Relevant code added :) – Darren Black May 31 '16 at 10:22
  • Why the downvote? o_O – Darren Black May 31 '16 at 10:32
  • 1
    You don't want to dispatch back to your queue, because that can easily lead to deadlocks. If it's a serial queue, it _will_ lead to deadlocks. There's no particular reason why calling `markAsFinished` should have threading issues. There's more going on. – Avi May 31 '16 at 11:00
  • @Avi Well the call to markAsFinished occurs on the main thread, while the NSOperation is on a background thread. This is surely a problem? If the KVO notifications aren't being sent on the same thread that they're being listened for, from what I've read, I won't get the desired behaviour. – Darren Black May 31 '16 at 11:44
  • Observers are called synchronously, so they are always called from the same thread the KVO notification is posted from. You don't specify a thread or queue when you register an observer. – Avi May 31 '16 at 11:47
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/113409/discussion-between-darren-black-and-avi). – Darren Black May 31 '16 at 12:01
  • I'm running into the same issue, I think.. did you ever come up with a solution to this? Thanks! @DarrenBlack – Laura Apr 23 '19 at 17:13
  • @Laura Sorry for the delay here, but I added an answer that was deleted by the admins. The content was this: "@Avi was correct; my issue had nothing to do with threading here. I'd forgotten to implement the getters for the isExecuting and isFinished properties." – Darren Black Oct 27 '19 at 11:31
  • Hopefully this helps, since it was so long ago that I can't remember the details of this :) – Darren Black Oct 27 '19 at 11:32

0 Answers0