在不同的线程上调用我的方法有什么不同的方法? [英] What are the different ways for calling my method on separate thread?

查看:157
本文介绍了在不同的线程上调用我的方法有什么不同的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

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

b)使用简单的快捷方式从继承的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,



目前,我使用了caseb,但好奇的优点和缺点和其他相关建议。



UPDATE:e)也找到了另一种执行类似线程处理的方法 - 运行循环。下面是来自苹果文档的摘录:


运行循环是一个事件处理循环,用于调度工作和协调接收到的事件。




p> 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将保留方法调用顺序。下面是一个例子:

  //将你的方法调用包装到NSInvocationOperation对象
NSInvocationOperation * currentOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(yourMethodCall)object:nil];

// _sharedOperationQueue是一个共享的NSOperationQueue
//从队列中获取所有执行操作并获取最后一个操作
_lastOperation = [[_sharedOperationQueue operations] lastObject];

//检查_lastOperation是否为nil
if(_lastOperation){

//如果不是,则添加依赖性,因此调用将在队列中执行
[currentOperation addDependency:_lastOperation];
}

//说 - 执行我的方法(操作)
[_sharedOperationQueue addOperation:currentOperation];

_lastOperation = currentOperation; //标记为向下一个操作添加依赖的最后一个操作

//队列将保留调用操作,因此您将释放
[currentOperation release];

.....你可以创建另一个NSInvocationOperation并将其添加到队列....

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

解决方案

通常, GCD方法。



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

使用纯线程时,问题是您可能会遇到性能问题,具体取决于可用核心/处理器的数量。



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



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



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



但是,由于这个原因,任务与GCD一起启动可能不是实时的。



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



希望这将有助于:)



EDIT



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



编辑2



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



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



/ strong>



所有这一切都在并发编程指南。它讨论了GCD和线程方法,有很多关于使用和实现的细节。



如果你还没有阅读它,你应该看看。 / p>

I have some data calculation method (let it be "myMethod:"), and I want to move the call to another thread because I don't want to block my main UI functionality. So, started to do some research on how to call my method on another thread. As far as I see, currently, there are a lot of different ways for doing that. Here's a list:

a) using pure threads (available since iOS 2.0):

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

b) using a simple shortcut (available since iOS 2.0). Available from inherited NSObject but the method belongs to NSThread class too:

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

c) using a new approach of Grand Central Dispatch queues (available since iOS 4.0):

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

d) somehow, using some classes such as NSOperation, NSBlockOperation or NSOperationQueue, though not sure how exactly to do it (some example would be appreciated)

Currently, I have used case "b" but curious about pros and cons and other related suggestions on that.

UPDATE: e) also found another way for performing similar threading stuff - Run loops. Here's an excerpt from apple docs:

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, more or less your are dealing with the same task - how to call your method on separate thread for its async operation.

UPDATE2: Already had some experience with NSInvocationOperation and NSOperationQueue and IMHO it's quite convenient. According to Apple docs, GCD and NSOperations are a preferred way for implementing multithreading. And also, NSOperations runs on GCD starting from iOS 4.0. In short, you instantiate NSIvocationOperation (as a call to your method) then instantiate NSOperationQueue and add invocation to the queue. NSOperationQueue is smart thing enough, you can instantiate multiple NSIvocationOperation objects (wrapping your method calls) and them to NSOperationQueue. The rest is assured. NSOperationQueue determines how much parallel threads it need to perform the calls (NSInvocationOperation) and handles it for you. It might execute first call on thread A, then second on thread B, third on thread C and forth on thread B, so you do not have to worry about that. But if you want, you may tell how max threads NSOperationQueue can use for performing calls (for example 1) but I have no need for that. By default, all tasks are performed on other than main thread, so operation queues are asynchronous by default. Also, if you want to perform your method calls (each wrapped in separate NSInvocationOperation) in a strict queue then you can add dependencies and so NSOperationQueue will preserve method call order. Here's an example:

// 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....

As for RUNLOOPs, still, sometimes you will face them, for example when starting/scheduling a timer, or making NSURL connections. IMHO, a runloop might be compared to a queue of tasks executed on one thread. IMHO a runloop is a pointer to a thread that operates as a queue: it has tasks that might throw events and they will be placed at the end of the queue in that thread. By default all tasks in your app run in a single runloop - in a single thread. I'm saying it's a pointer because when your app generates events then the app must know where to put that event (touch event or other delegate callback) for execution. Of course, you should read about runloops for more detailed information because these are just my thoughts.

解决方案

Usually, you would prefer the GCD approach.

It's simpler when it comes to synchronization/locking than pure threads (NSThread - pthread), and it may be more accurate in a performance perspective.

When using pure threads, the problem is you may have performance issues, depending on the number of available cores/processors.

For instance, if you have only one core, creating many threads may slow down your application, because the CPU will spend most of its time switching from one thread to another, saving the stack, registers, etc.

On the other hand, if you have a lot of cores available, it may be nice to create a lot of different threads.

This is where GCD helps, as it manages this for you. It will create the appropriate number of threads, based on the available system resources, to guarantee an optimal utilization, and schedule your actions appropriately.

However, for that reason, tasks launched with GCD may not be real-time.

So if you REALLY needs that a detached task runs immediately, use an explicit threads. Otherwise, use GCD.

Hope this will help you : )

EDIT

A note about performSelectorInBackground: it simply creates a new thread. So there's basically no difference with the NSThread approach.

EDIT 2

NSOperation related stuff are a bit different. On Mac OS X, they are implemented using GCD since version 10.6. Previous versions uses threads.

On iOS, they are implemented using threads only.

Reference

All of this is very well explained in the Concurrency Programming Guide. It discusses the GCD and thread approaches, with a lot of details about the uses and implementations.

If you haven't read it already, you should take a look.

这篇关于在不同的线程上调用我的方法有什么不同的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆