9

我创建了一个 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线路的违规行为。

4

1 回答 1

7

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

主操作队列在主线程上运行。从文档中+[NSOperationQueue mainQueue]

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

因此,在另一个线程中运行取决于您将操作添加到哪个队列,而不是您如何编写操作代码。如果您希望您的操作在不同的操作队列上运行,您需要使用创建自己的队列

NSOperationQueue* aQueue = [[NSOperationQueue alloc] init];

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

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

听起来-[NSOperation start]可能不是可重入的。您的代码在两个不同的线程上有效地执行相同的方法。事实上,查看文档-start,很明显您的代码将无法正常工作:

如果要手动执行操作,可以显式调用此方法。但是,对已经在操作队列中的操作对象调用此方法 或在调用此方法后将操作排队是程序员的错误。将操作对象添加到队列后,队列将承担所有责任。[强调补充。-迦勒]

换句话说,不要那样做。

于 2013-08-05T03:12:54.610 回答