iPhone iOS 在单独线程上运行

96

如何在单独的线程上运行代码?是以下哪种方法最好:

[NSThread detachNewThreadSelector: @selector(doStuff) toTarget:self withObject:NULL];

或者:

    NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
                                                                        selector:@selector(doStuff:)
                                                                          object:nil;
[queue addOperation:operation];
[operation release];
[queue release];

我一直在使用第二种方法,但我正在阅读的Wesley Cookbook却使用第一种方法。

4个回答

244

在我看来,最好的方法是使用libdispatch,也称为Grand Central Dispatch(GCD)。它限制了你必须使用iOS 4或更高版本,但是它非常简单易用。在后台线程上处理一些任务并在主运行循环中对结果进行处理的代码非常简单和紧凑:

dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // Add code here to do background processing
    //
    //
    dispatch_async( dispatch_get_main_queue(), ^{
        // Add code here to update the UI/send notifications based on the
        // results of the background processing
    });
});

如果您还没有这样做,请查看WWDC 2010有关libdispatch/GCD/blocks的视频。


我需要它兼容3.0版本 :( - Mike S
1
然后操作队列可能是下一个最好的解决方案。另外,确保您不要太快地进入并发。尝试从单线程编写并进行分析,以查看是否需要使用多线程,或者是否可以设计单线程代码以使其自行更高效。对于简单的任务,有时您可以使用performSelector:withObject:afterDelay:完成所需的所有操作,并避免多线程编程带来的所有问题。 - Jacques
抱歉这么晚才回复,但如果我使用performSelector:withObject:afterDelay来生成一个方法调用,我是否仍需要在异步方法中使用NSAutoReleasePool?如果它自动使用主自动释放池,那么performSElector:afterDelay肯定是更快的选择。 - Mike S
4
有风险说出你可能已经知道的事,你不应该养成编写会终止线程的代码的习惯,从长远来看这对你和你的职业生涯都没有好处。请参考此帖子(或类似的帖子)以了解为什么不要终止线程。 - MikeC
我因为使用了文档中提到的 QOS_CLASS_BACKGROUND 而导致程序崩溃。而在该行代码上方有明确说明,可以使用其他值,例如 DISPATCH_QUEUE_PRIORITY_DEFAULT。由于匆忙之下没有注意到这一点,才会出现这个问题。 - Martin Berger
显示剩余4条评论

1
在iOS中进行多线程编程的最佳方式是使用GCD(Grand Central Dispatch)。
//creates a queue.

dispatch_queue_t myQueue = dispatch_queue_create("unique_queue_name", NULL);

dispatch_async(myQueue, ^{
    //stuffs to do in background thread
    dispatch_async(dispatch_get_main_queue(), ^{
    //stuffs to do in foreground thread, mostly UI updates
    });
});

0

我会尝试所有人发布的技术,并查看哪种方法最快,但我认为这是最好的方法。

[self performSelectorInBackground:@selector(BackgroundMethod) withObject:nil];

这将以低优先级启动线程。使用GCD是线程的最佳方式。 - Karsten

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接