objective-c – 在不同的线程调用我的方法有什么不同的方法?

我有一些数据计算方法(让它是“myMethod:”),我想移动调用到另一个线程,因为我不想阻止我的主要UI功能。所以,开始做一些研究如何调用我的方法在另一个线程。据我所知,目前有很多不同的方法。这里有一个列表:

a)使用纯线程(自iOS 2.0起可用):

[NSThread detachNewThreadSelector:@selector(myMethod:) toTarget:self withObject:_myParamsArray];

b)使用简单的快捷方式(自iOS 2.0起可用)。从继承的NSObject可用,但该方法也属于NSThread类:

[self performSelectorInBackground:@selector(myMethod:) withObject:_myParamsArray];

c)使用Grand Central Dispatch队列的新方法(自iOS 4.0起可用):

dispatch_async(dispatch_get_global_queue(0, 0),
  ^ {
      [self myMethod:_myParamsArray];
    });

d)不知何故,使用一些类,如NSOperation,NSBlockOperation或NSOperationQueue,虽然不知道如何确切地做到(一些例子会赞赏)

目前,我使用了情况“b”,但好奇的利弊和其他相关建议。

更新:e)也找到了另一种方式来执行类似的线程的东西 – Run loops.这里是一个摘录从苹果文档:

A run loop is an event processing loop that you use to schedule work and coordinate the receipt of incoming events. The purpose of a run loop is to keep your thread busy when there is work to do and put your thread to sleep when there is none.

IMHO,或多或少你正在处理相同的任务 – 如何调用您的方法在单独的线程为其异步操作。

UPDATE2:已经有NSInvocationOperation和NSOperationQueue和IMHO的一些经验,它是相当方便。根据苹果文档,GCD和NSOperations是实现多线程的首选方式。而且,NSOperations从iOS 4.0开始在GCD上运行。简而言之,您实例化NSIvocationOperation(作为对您的方法的调用),然后实例化NSOperationQueue和添加调用到队列。 NSOperationQueue是聪明的东西够了,你可以实例化多个NSIvocationOperation对象(包装你的方法调用)和他们到NSOperationQueue。其余的是放心。 NSOperationQueue确定需要多少并行线程执行调用(NSInvocationOperation)并为您处理它。它可以在线程A上执行第一次调用,然后在线程B上执行第二次,在线程C上执行第三次,在线程B上执行,因此您不必担心。但是如果你想,你可以告诉NSOperationQueue可以用来执行调用的最大线程(例如1),但我不需要。默认情况下,所有任务都在主线程之外执行,因此操作队列在默认情况下是异步的。此外,如果你想在一个严格的队列中执行你的方法调用(每个包裹在单独的NSInvocationOperation),那么你可以添加依赖,所以NSOperationQueue将保留方法调用顺序。这里有一个例子:

// wrap your method call into NSInvocationOperation object
NSInvocationOperation *currentOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(yourMethodCall) object:nil];

// _sharedOperationQueue is a shared NSOperationQueue 
// get all executing operations from the queue and get the last operation
_lastOperation = [[_sharedOperationQueue operations] lastObject];

// check if _lastOperation is not nil
if (_lastOperation) {

    // if not then add dependency, so the calls would be performed in a queue
    [currentOperation addDependency:_lastOperation];
}

// say - execute my method (operation)
[_sharedOperationQueue addOperation:currentOperation];

_lastOperation = currentOperation; // mark as last operation for adding dependency to the next operation

// the queue will retain invocation operation so you will release
[currentOperation release];

 ..... you can create another NSInvocationOperation and add it to the queue....

至于RUNLOOP,仍然,有时你会面对他们,例如当启动/调度定时器,或做NSURL连接。 IMHO,runloop可能与在一个线程上执行的任务队列进行比较。 IMho runloop是指向作为队列操作的线程的指针:它有可能抛出事件的任务,它们将被放置在该线程中队列的末尾。默认情况下,应用程序中的所有任务都在单个runloop中运行 – 在单个线程中。我说这是一个指针,因为当你的应用程序生成事件,那么应用程序必须知道在哪里放置该事件(触摸事件或其他代理回调)执行。当然,你应该阅读关于runloops更详细的信息,因为这些只是我的想法。

最佳答案
通常,你更喜欢GCD方法。

当涉及到同步/锁定比纯线程(NSThread – pthread)更简单,它可能在性能透视更准确。

当使用纯线程时,问题是您可能有性能问题,这取决于可用的核心/处理器的数量。

例如,如果你只有一个核心,创建许多线程可能会减缓你的应用程序,因为CPU将花费大部分时间从一个线程切换到另一个线程,保存堆栈,寄存器等。

另一方面,如果你有很多内核可用,可能会很好创建很多不同的线程。

这是GCD帮助的地方,因为它为你管理。它将基于可用的系统资源创建适当数量的线程,以确保最佳利用率,并适当地调度您的操作。

然而,由于这个原因,使用GCD启动的任务可能不是实时的。

所以如果你真的需要一个分离的任务立即运行,使用显式线程。否则,使用GCD。

希望这将帮助你:)

编辑

关于performSelectorInBackground的注释:它只是创建一个新的线程。因此,与NSThread方法基本没有区别。

编辑2

NSOperation相关的东西有点不同。在Mac OS X上,从版本10.6开始使用GCD实现。以前的版本使用线程。

在iOS上,它们仅使用线程实现。

参考

所有这些都在Concurrency Programming Guide中有很好的解释。它讨论了GCD和线程方法,有很多关于使用和实现的细节。

如果你还没有读过它,你应该看看。

转载注明原文:objective-c – 在不同的线程调用我的方法有什么不同的方法? - 代码日志