使用NSOperationQueue,如何添加到后台队列而不是main,以及控制操作量如何工作?

时间:2014-01-13 16:41:02

标签: ios objective-c concurrency nsoperation nsoperationqueue

我很喜欢NSOperationQueue,但我在理解其中某些部分时遇到了一些问题。

the second issue of objc.io中,他们回顾了NSOperationQueue,并提到它有两种队列,即主线程上运行的主队列和后台队列。他们提到您可以使用[NSOperation mainQueue]访问主队列,然后添加操作它。

  • 你通常不想这样做,对吗?如果它在主线程上运行,它是否会阻止主线程执行其他任务?不会与其他任务同时运行吗?

它还提到你可以通过创建NSOperation的实例(潜在的子类)来添加到后台队列(我理解会更好吗?)。

  • 我是否保存对我为操作创建的NSOperationQueue的引用,以便创建更多操作?我假设没有像mainQueue这样的后台队列单例,那么如何管理向后台队列添加任务呢?

它还提到您可以控制与maxConcurrentOperationCount属性同时运行的操作量。

  • 我通常知道您将其设置为NSOperationQueueDefaultMaxConcurrentOperationCount,但如果我手动将其设置为特定数字,它是否与一次可以运行的最大线程数相对应?例如,如果iPhone上的处理器可以同时运行4个线程并且我将该属性设置为8,会发生什么?

3 个答案:

答案 0 :(得分:17)

你问:

  

您通常不希望[向mainQueue添加操作],对吗?如果它在主线程上运行,它是否会阻止主线程执行其他任务?它不会与其他任务同时运行吗?

是的,你永远不想在主队列中添加任何慢的东西。但这并不意味着您不使用主队列。对于某些操作(例如UI更新),这很关键。

典型的模式是为要在后台运行的任务创建操作队列,但是如果您随后需要执行需要在主队列上运行的操作(例如UI更新,更新模型等)。 ),你会继续这样做,例如:

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

[queue addOperationWithBlock:^{
    // do some time consuming stuff in the background

    // when done, you might update the UI in the main queue

    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        // update the UI here
    }];
];

你问:

  

我是否保存对我为操作创建的NSOperationQueue的引用,以便创建更多操作?我假设没有像mainQueue那样的后台队列单例,那么如何管理向后台队列添加任务呢?

是的,如果您想稍后向同一队列添加更多操作,是的,您希望维护对该队列的引用。您可以通过将其添加到应用程序委托,某个中央视图控制器或单例来完成此操作。

但是,是的,背景队列没有内置的单例(因为可以想象,不同的队列可以有不同的操作,例如一个用于网络操作,一个用于图像处理等)。但是,如果需要,您可以为每种类型的每个队列编写自己的单例。

你也问:

  

我通常知道您将其设置为NSOperationQueueDefaultMaxConcurrentOperationCount,但如果我手动将其设置为特定数字,它是否与一次可以运行的最大线程数相对应?例如,如果iPhone上的处理器可以同时运行4个线程并且我将该属性设置为8,会发生什么?

应该将maxConcurrentOperationCount设置为您认为适合队列类型的任何内容。对于网络操作队列,通常不会超过4,但对于其他类型的队列,您可能很容易拥有更多。我相信最多有64个工作线程(并发队列因为需要线程而自行使用)。

如果您尝试使用更多,则在工作线程可用之前,应用程序将不会启动您的操作。不过,Apple建议不要使用所有工作线程。因此,请使用适合您队列功能的合理数字。坦率地说,操作队列优于调度队列的一个优点是,您可以限制在任何给定时间将使用的最大工作线程数,以更好地管理设备的有限资源。


参考

答案 1 :(得分:0)

通常您不想使用主队列。那里的任何操作都将在主线程上运行。

创建操作队列时,请将其创建用于某个目的。就像它将用于所有服务器请求。因此,您可以控制正在进行的并发请求数。因此,不要将算法处理操作添加到此队列,因为它们具有不同的用途。保留对队列的引用,以便将来添加操作(以及暂停/取消操作)。

maxConcurrentOperationCount没有“正常”设置 - 应根据目的设置。

如果将其设置为8,则队列将同时运行最多8个。这可能不是最有效的选择。始终牢记队列的目的。

答案 2 :(得分:0)

首先,您必须记住,您始终将主线程与后台线程分开。只有涉及更新UI的操作必须在主线程中执行,其余操作必须在后台线程中执行。例如,如果您正在处理多次下载,则必须在后台队列中处理所有基于网络的操作,并且您必须在主队列中执行UI更新。

//e.g for updating UI in main thread.
[self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:YES];

当您使用set maxConcurrentOperationCount属性作为NSOperationQueueDefaultMaxConcurrentOperationCount时,这意味着operationQueue将根据系统环境获取并发操作的数量。

有用的链接:

http://mobile.tutsplus.com/tutorials/iphone/nsoperationqueue/

http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues

http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/