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直到SomeOperation對象,operation1main啓動異步任務,調用其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