从NSOperationQueue获取底层dispatch_queue_t

时间:2013-05-15 11:07:07

标签: ios grand-central-dispatch afnetworking nsoperationqueue

我似乎在dispatch_queue_tNSOperationQueue队列之间存在一些混淆。

默认情况下,AFNetworking的AFImageRequestOperation将在应用程序的主线程上执行成功回调块。要更改此设置,AFHTTPRequestOperation具有属性successCallbackQueue,可让您选择运行回调的队列。

我正在尝试在已经执行HTTP请求的相同后台队列/后台线程上执行成功回调。而不是返回到主线程,运行的NSOperationQueue HTTP请求也应该运行回调,因为我需要使用一些返回的图像进行一些繁重的计算。

我的第一次尝试是将successCallbackQueue设置为NSOperationQueue运行的AFImageRequestOperation实例。但是,successCallbackQueue属性的类型为dispatch_queue_t,因此我需要一种方法来获取dispatch_queue_t实例的基础NSOperation,如果有的话是这样的事情。

这可能,还是我需要创建单独的dispatch_queue_t

我问的原因:AFNetworking继承自NSOperation有点奇怪,但我们希望我们使用dispatch_queue_t队列进行回调。混合两种范式dispatch_queue_tNSOperationQueue

感谢任何提示!

6 个答案:

答案 0 :(得分:8)

没有这样的事情,NSOperationQueuedispatch_queue_t之间没有一对一的对应关系,两个API中的排队概念非常不同(例如,NSOperationQueue没有像GCD一样有严格的FIFO排队。

NSOperationQueue用于执行代码的唯一调度队列是默认优先级全局并发队列。

答案 1 :(得分:5)

NSOperationQueue不是AFNetworking的瓶颈。请求操作受网络绑定,而不是CPU或内存。所有工作都在调度队列中异步完成,调度队列可以作为AFHTTPRequestOperation中的属性进行访问。

不建议使用网络线程进行任何处理。这不会以任何方式改善性能。

相反,如果您注意到性能问题,请尝试限制操作队列中的最大并发操作数,以间接控制这些后台处理队列所完成的工作量。

答案 2 :(得分:3)

有趣的是,AFHTTPClient使用NSOperationQueue来运行AFHTTPRequestOperations,但使用GCD dispatch_queues来处理结果。

关于NSOperationQueue,Apple文档说:

  

注意:在iOS 4及更高版本中,操作队列使用Grand Central Dispatch执行操作。

但似乎没有公共API来获取给定操作的dispatch_queue。

如果成功回调必须与原始操作执行完全相同的队列/线程并不重要,那么为什么不设置:

successCallbackQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0);

答案 3 :(得分:3)

适用于iOS 8.4的XCode 6.4,启用了ARC

1)“......所以我需要一种方法来获取我的NSOperation实例的底层dispatch_queue_t,如果有这样的话。”

NSOperationQueue有一个属性可以提供帮助:

@property(assign) dispatch_queue_t underlyingQueue

可以按如下方式分配给NSOperationQueue:

NSOperationQueue *concurrentQueueForServerCommunication = [[NSOperationQueue alloc] init];
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    concurrentQueueForServerCommunication.underlyingQueue = concurrentQueue;

或者从NSOperationQueue分配:

NSOperationQueue *concurrentQueueForServerCommunication = [[NSOperationQueue alloc] init];
dispatch_queue_t concurrentQueue = concurrentQueueForServerCommunication.underlyingQueue;

在网络任务完成后,不确定您用于网络通信的API是否会更新您的UI,但是如果它没有,那么您必须知道在执行完成块时返回到主队列:< / p>

dispatch_sync(dispatch_get_main_queue(), ^{

//Update your UI here...

}

希望这有帮助!欢呼声。

答案 4 :(得分:1)

首先,在主线程上执行AFImageRequestOperation的成功是一个很好的行为,因为此操作的主要用途是在后台下载图像并在UI上显示(应该是在主线程上),但为了满足那些想要在其他线程上执行回调的用户(你的情况)的需求,还有一个successCalbackQueue。

因此,您可以使用dispatch_queue_create方法或建议的方法创建自己的dispatch_queue_t,您应该使用dispatch_get_global_queue来获取主队列。

在每种情况下,请确保在您的成功阻止中,如果您对UI进行了一些更改,请将它们放在dispatch_async(dispatch_get_main_queue(), ^{ // main op here});

答案 5 :(得分:0)

Swift 3代码,基于@ serge-k的答案:

// Initialize the operation queue.
let operationQueue = OperationQueue()
operationQueue.name = "com.example.myOperationQueue"
operationQueue.qualityOfService = .userInitiated

// Initialize a backing DispatchQueue so we can reuse it for network operations.
// Because no additional info is give, the dispatch queue will have the same QoS as the operation queue.
let operationQueueUnderlyingQueue = DispatchQueue(label: "com.example.underlyingQueue")
operationQueue.qualityOfService.underlyingQueue = operationQueueUnderlyingQueue

然后您可以通过以下方式在Alamofire(或AFNetworking)中使用它:

Alamofire.request("https://example.com/get", parameters: nil).validate().responseJSON(queue: operationQueue.underlyingQueue) { response in
    response handler code
}

此处有一条警告,来自Apple关于设置OperationQueue基础队列的文档:

  

只有在队列中没有操作时才应设置此属性的值;当operationCount不等于0时设置此属性的值会引发invalidArgumentException。此属性的值不能是dispatch_get_main_queue()返回的值。为基础调度队列设置的服务质量级别将覆盖为操作队列的qualityOfService属性设置的任何值。