NSOperation不会在后台线程中发生

时间:2013-08-05 02:18:22

标签: ios objective-c grand-central-dispatch nsoperation nsoperationqueue

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

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

知道发生了什么事吗?

我尝试添加此块:

- (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...
    }

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

1 个答案:

答案 0 :(得分:7)

  

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

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

  

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

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

创建自己的队列
NSOperationQueue* aQueue = [[NSOperationQueue alloc] init];

您可以在“并发编程指南”中找到Adding Operations to an Operation Queue中的示例。

  

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

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

  

如果你想执行你的方法,你可以明确地调用这个方法   手动操作。但是,调用它是一个程序员错误   已经在操作队列中的操作对象的方法   或者在调用此方法后对操作进行排队。一旦你添加了   操作对象到队列,队列承担所有责任   它。 [重点补充。 -Caleb]

换句话说,不要这样做。