我似乎在dispatch_queue_t
和NSOperationQueue
队列之间存在一些混淆。
默认情况下,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_t
和NSOperationQueue
。
感谢任何提示!
答案 0 :(得分:8)
没有这样的事情,NSOperationQueue
和dispatch_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
属性设置的任何值。