NSOperationQueue setSuspended:NO不启动队列,NSLog没有

时间:2012-07-17 23:09:08

标签: objective-c ios nsoperation nsoperationqueue

我有一个非并发的NSOperation正在运行,其中有一部分在其中进行了大量的网络调用并处理了结果。这似乎是并行化的一个简单目标,所以我做了以下几点:

NSOperationQueue *downloadOperationQueue = [[NSOperationQueue alloc] init];
downloadOperationQueue.maxConcurrentOperationCount = 5;

self.operationThread = [NSThread currentThread];
//prevent the operation queue from starting until we're ready to receive events
[downloadOperationQueue setSuspended:YES];

for (FooInfo *fooInfo in foos)
{
    //FooDownloadOperation is a non-concurrent operation.
    FooDownloadOperation *downloadOp = [[FooDownloadOperation alloc] initWithFoo:fooInfo];
    downloadOp.delegate = self;
    [downloadOperationQueue addOperation:downloadOp];
}
//unsuspend the queue and spin a run loop until the local operation count hits zero
[downloadOperationQueue setSuspended:NO];
while (self.isCancelled == NO && [downloadOperationQueue operationCount] > 0) 
{
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1.0f]];
}
// ... do other things

还有另一种方法 - 在FooDownloadOperation调用中,它执行performSelector:onThread:跳回self.operationThread来处理结果:

- (void)downloadOperation:(FooDownloadOperation *)downloadOp didSucceed:(NSArray *)results
{
    if ([[NSThread currentThread] isEqual:self.operationThread] == NO)
    {
        //too many arguments for -performSelector:onThread:withObject:waitUntilDone:
        NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:_cmd]];
        [inv setTarget:self];
        [inv setSelector:_cmd];
        [inv setArgument:&downloadOp atIndex:2];
        [inv setArgument:&results atIndex:3];
        [inv retainArguments];
        [inv performSelector:@selector(invoke) onThread:self.operationThread withObject:nil waitUntilDone:YES];
        return;
    }

    //... process the results
}

没问题。理论上。

事实上,大约70%的时间,从睡眠状态唤醒设备并运行操作后更糟糕的是,它只是在while循环中,-runMode:untilDate:返回NO。奇怪的是,在20秒到6分钟之间,FooDownloadOperations终于开始了。

为了让事情更奇怪,如果我在while循环中添加日志记录,它会按预期开始工作。我可以添加一些日志记录,但我真的很想知道为什么这似乎解决了这个问题。

1 个答案:

答案 0 :(得分:0)

你的混合比喻可以这么说。如果您的NSOpeations不是并发的,则不必担心runloop - 您无法在运行时向它们发送消息(如果您需要该功能,则需要并发操作,并且应该在github上查看有关如何使用这些内容的大量示例)。

所以,你不需要知道当前的线程(这是主应用程序的当前线程,而不是操作(在你的代码中)。所以你创建一个队列,你暂停它,你添加了一大堆要运行的操作,然后当你想要告诉队列运行时,你可以等待队列完成,或者你可以轮询它等等。