1

我有一个非并发的 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

还有另一种方法 -main 在 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 循环中添加日志记录,它会按预期开始工作。我可以添加一些日志记录,但我真的很想知道为什么这似乎可以解决问题。

4

1 回答 1

0

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

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

于 2012-07-18T00:51:21.057 回答