Ios NSOperationQueue:无法理解订单
我无法理解Ios NSOperationQueue:无法理解订单,ios,objective-c,multithreading,cocoa-touch,objective-c-blocks,Ios,Objective C,Multithreading,Cocoa Touch,Objective C Blocks,我无法理解NSOperationQueue的工作方式 假设我有: NSOperationQueue *queue = [[NSOperationQueue alloc] init]; queue.maxConcurrentOperationCount=1; [queue addOperationWithBlock:^{ [someObject someSelector]; }]; [queue addOperationWithBlock:^{
NSOperationQueue
的工作方式
假设我有:
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount=1;
[queue addOperationWithBlock:^{
[someObject someSelector];
}];
[queue addOperationWithBlock:^{
[someObject anotherSelector];
}];
第二个块甚至在第一个块完成之前就被调用了,这与我想要的正好相反。我尝试改用–performSelectorOnMainThread:withObject:waitUntilDone:
,但第二个块仍在首先执行——可能是因为块线程没有在主线程上完成,因此它没有被waitUntilDone阻塞。我在someSelector块中添加了一个断点,它是在第二个块中的断点之后到达的
我不太明白。救救我 如果操作之间存在明确的依赖关系,则使用
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
消息)
因此,使用下面的代码,它不会启动operation2
,直到SomeOperation
对象operation1
中的main
中启动的异步任务调用其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];
我还是不太明白。为了保证FIFO,我应该对我的代码做什么?我认为必须设置操作依赖项来保证操作顺序。只需使用
addDependency
就可以了,除非这两种方法中的任何一种都是异步运行的,在这种情况下,您可能需要使用NSOperation
子类。啊,是的,这是我的问题。在我的someSelector方法中是对执行同步URL请求的NSObject的调用,但我猜对该方法的调用本身是异步的。具体来说,它看起来像data=[customObject getDataWithURL:(NSString*)url]——但不能对具有返回值的对象调用PerformSelect或WaitUntildOne。我打算调查NSInvocation,在这种情况下这是正确的做法吗?我在这里提出了一个新问题:没有解决我的特殊问题,但肯定回答了我提出的问题。@JoshDG我已经用示例代码更新了我的答案,用于将异步任务包装到自定义的NSOperation
中,在异步过程完成之前,它不会发布isFinished
。非常感谢所有这些代码!所以,正如您所说,最终发生的事情是,我将对NSURLConnection的调用放在另一个NSOperationQueue中,我猜这样做是将它放在另一个线程中?我最后取出了第二个操作队列,现在它按预期运行。我的推理正确吗?@JoshDG Yep,这完全有道理:将添加到队列中的块本身同步(例如通过消除冗余操作队列),这样就可以修复它。当您无法(或不想)使提交的操作同步时(例如,通常人们不喜欢使用sendSynchronousRequest
,因为您会丢失很多功能),上述将异步进程包装到自定义NSOperation
中的技术是一种有用的模式。但是看起来你有一些适合你的东西。我真的很感谢你的帮助!
// 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
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];