NSOperation不会在后台线程中发生

Jus*_*tin 9 objective-c nsoperation nsoperationqueue grand-central-dispatch ios

我创建了一个NSOperation子类来处理一些zip存档操作.无论如何,如果我覆盖-start或者-main这段代码总是发生:

if ([NSThread isMainThread]) {
    NSLog(@"I am in the main thread");
    return;
}
Run Code Online (Sandbox Code Playgroud)

知道发生了什么事吗?

我试过添加这个块:

- (void) start {  //also tried overriding main

    if ([NSThread isMainThread]) {
        NSLog(@"In main thread, trying again");
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self start];
        });
        return;
        //hard working code etc...
        //cpu intensive zip operations...
    }
Run Code Online (Sandbox Code Playgroud)

但这会导致崩溃,EXC_BAD_ACCESS违规指向该dispatch_async线.

Cal*_*leb 7

无论如何,如果我覆盖-start或-main这段代码总是会发生:

主操作队列在主线程上运行.来自以下文档+[NSOperationQueue mainQueue]:

返回的队列在主线程上执行操作.主线程的运行循环控制这些操作的执行时间.

因此,在另一个线程中运行是您添加操作的队列的问题,而不是您编写操作代码的方式.如果希望操作在不同的操作队列上运行,则需要使用自己的队列创建

NSOperationQueue* aQueue = [[NSOperationQueue alloc] init];
Run Code Online (Sandbox Code Playgroud)

您可以在"并发编程指南"中找到"向操作队列添加操作"中的示例.

但这会导致崩溃,指向dispatch_async行的EXC_BAD_ACCESS违规.

听起来好像-[NSOperation start]不是可重入的.您的代码在两个不同的线程上有效地执行相同的方法.事实上,看看文档-start,显然你的代码不起作用:

如果要手动执行操作,可以显式调用此方法.但是,在已经在操作队列中的操作对象上调用此方法 或在调用此方法后对操作进行排队是一个程序员错误.将操作对象添加到队列后,队列将承担全部责任.[重点补充说.-Caleb]

换句话说,不要这样做.