10

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

默认情况下,AFNetworkingAFImageRequestOperation将在应用程序的主线程上执行成功回调块。要改变这一点,AFHTTPRequestOperation具有successCallbackQueue允许您选择在哪个队列上运行回调的属性。

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

我的第一次尝试是设置successCallbackQueue为运行的NSOperationQueue实例AFImageRequestOperation。但是,该successCallbackQueue属性是 type ,所以如果有这样的事情dispatch_queue_t,我需要一种方法来获取我的instance的底层。dispatch_queue_tNSOperation

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

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

感谢您的任何提示!

4

6 回答 6

9

NSOperationQueue没有这样的东西,不存在 an和 a的一一对应,dispatch_queue_t两个 API 中的排队概念非常不同(例如 NSOperationQueue 没有像 GCD 那样严格的 FIFO 排队)。

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

于 2013-05-15T22:40:42.563 回答
5

NSOperationQueue不是 AFNetworking 的瓶颈。请求操作受网络约束,而不是 CPU 或内存。所有工作都是在调度队列中异步完成的,可以作为AFHTTPRequestOperation.

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

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

于 2013-05-23T16:28:31.707 回答
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);
于 2013-05-15T11:32:31.180 回答
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,但以防万一,您必须知道在执行完成块时返回主队列:

dispatch_sync(dispatch_get_main_queue(), ^{

//Update your UI here...

}

希望这可以帮助!干杯。

于 2015-08-10T21:50:09.377 回答
1

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

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

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

于 2013-05-15T11:38:12.120 回答
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属性设置的任何值。

于 2017-08-07T15:03:50.037 回答