3

У меня возникли проблемы с пониманием пути работы NSOperationQueue.NSOperationQueue: непонимание порядка

Скажем, у меня есть:

NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
     queue.maxConcurrentOperationCount=1; 

     [queue addOperationWithBlock:^{ 
[someObject someSelector]; 
}]; 

     [queue addOperationWithBlock:^{ 
[someObject anotherSelector]; 
}]; 

Второй блок вызывается еще до первого блока заканчивается - противоположность того, что я хочу. Я попробовал использовать - performSelectorOnMainThread:withObject:waitUntilDone: вместо этого, но второй блок все еще выполняется первым - предположительно потому, что поток блоков не выполняется в основном потоке, и поэтому он не блокируется с помощью waitUntilDone. Я добавил точку останова внутри блока someSelector, и это достигается после точки останова внутри второго блока.

Я не совсем понимаю. Помоги мне!!

+0

Я все еще не совсем понимаю. Что мне делать с моим кодом, чтобы гарантировать FIFO? – JoshDG

+0

Я думаю, что вы должны установить операционные зависимости, чтобы гарантировать порядок операций. –

+0

Просто использование 'addDependency' будет выполнять задание, если ни один из этих методов не выполняет ничего, что есть, сам, работает асинхронно, и в этом случае вы, вероятно, захотите использовать подкласс NSOperation. – Rob

ответ

4

Если есть явные зависимости между операциями, а затем использовать addDependency:

NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
queue.maxConcurrentOperationCount=1; 

NSOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{ 
    [someObject someSelector]; 
}]; 

NSOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{ 
    [someObject anotherSelector]; 
}]; 

[operation2 addDependency:operation1]; 

[queue addOperation:operation1]; 
[queue addOperation:operation2]; 

Если ваши операции делают асинхронной активности, то вы должны определить пользовательские операции и вызывать только completeOperation (который будет сообщение isFinished), когда выполняется асинхронная задача).

// SomeOperation.h 

#import <Foundation/Foundation.h> 

@interface SomeOperation : NSOperation 

@end 

и

// SomeOperation.m 

#import "SomeOperation.h" 

@interface SomeOperation() 
@property (nonatomic, readwrite, getter = isFinished) BOOL finished; 
@property (nonatomic, readwrite, getter = isExecuting) BOOL executing; 
@end 

@implementation SomeOperation 

@synthesize finished = _finished; 
@synthesize executing = _executing; 

#pragma Configure basic operation 

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     _finished = NO; 
     _executing = NO; 
    } 
    return self; 
} 

- (void)start 
{ 
    if ([self isCancelled]) { 
     self.finished = YES; 
     return; 
    } 

    self.executing = YES; 

    [self main]; 
} 

- (void)completeOperation 
{ 
    self.executing = NO; 
    self.finished = YES; 
} 

- (void)main 
{ 
    // start some asynchronous operation 

    // when it's done, call `completeOperation` 
} 

#pragma mark - Standard NSOperation methods 

- (BOOL)isConcurrent 
{ 
    return YES; 
} 

- (void)setExecuting:(BOOL)executing 
{ 
    [self willChangeValueForKey:@"isExecuting"]; 
    _executing = executing; 
    [self didChangeValueForKey:@"isExecuting"]; 
} 

- (void)setFinished:(BOOL)finished 
{ 
    [self willChangeValueForKey:@"isFinished"]; 
    _finished = finished; 
    [self didChangeValueForKey:@"isFinished"]; 
} 

@end 

Таким образом, с помощью следующего кода, он не начнет operation2 до асинхронная задача инициируется в main в SomeOperation объекта, operation1, не вызывает его метод completeOperation.

NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
queue.maxConcurrentOperationCount=1; 

NSOperation *operation1 = [[SomeOperation alloc] init]; 

NSOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{ 
    [someObject anotherSelector]; 
}]; 

[operation2 addDependency:operation1]; 

[queue addOperation:operation1]; 
[queue addOperation:operation2]; 
+0

Не решает мою конкретную проблему, но определенно отвечает на вопрос, который я задал. – JoshDG

+0

@JoshDG Я обновил свой ответ с помощью примера кода для упаковки вашей асинхронной задачи в пользовательском 'NSOperation', который не будет отправлять' isFinished' до тех пор, пока не будет выполнен асинхронный процесс. – Rob

+0

Спасибо, я очень ценю весь этот код! Итак, что, как вы предположили, закончилось тем, что я отправлял вызов NSURLConnection внутри другого NSOperationQueue, и я полагаю, что, сделав это, он был помещен в другой поток? Я закончил тем, что вынул вторую очередь операций, и теперь она работает так, как ожидалось. Я правильно это понял? – JoshDG

Смежные вопросы