释放GCD调度队列属性的正确方法是什么?

Mar*_*man 19 memory-management objective-c grand-central-dispatch

我正在使用dispatch_queue,它通过其所有者的属性访问,如下所示:

@property (nonatomic, assign) dispatch_queue_t queue;
Run Code Online (Sandbox Code Playgroud)

注意assign关键字.队列在整个对象生命周期中使用,因此由对象拥有.我取消分配拥有对象时释放队列:

-(void)dealloc
{
    dispatch_release(self.queue);
    self.queue = nil;
}
Run Code Online (Sandbox Code Playgroud)

我该如何正确发布?会用到retain/release工作吗?

如果在调用release时队列中有待处理/正在运行的东西,会发生什么?

Ste*_*tto 20

以下内容是从开发人员文档中窃取的:

调度队列和其他调度对象是引用计数数据类型.创建串行调度队列时,它的初始引用计数为1.您可以使用dispatch_retain和dispatch_release函数根据需要递增和递减该引用计数.当队列的引用计数达到零时,系统异步释放队列.

当您的应用程序不再需要调度队列时,它应该使用dispatch_release函数释放它.提交到队列的任何挂起块都会保留对该队列的引用,因此在完成所有挂起块之前不会释放队列.

注意:您无需保留或释放任何全局调度队列,包括并发调度队列或主调度队列.任何保留或释放队列的尝试都将被忽略.

因此,无论你在哪里使用-retain使用dispatch_retain,你都会使用-release使用dispatch_release.

Dispatch队列遵循与objective-c对象相同的一般内存管理约定.并且在排队的所有块完成之前,它们不会被解除分配.

如果你想要一种方法来关闭一个调度队列:没有办法通过任何类型的API取消所有排队的块,所以它们总是必须运行完成.加速此过程的一种方法是在管理调度队列的类中使用BOOL变量:_isValid.如果要关闭队列,可以将_isValid设置为NO.提交到队列的所有块应该在执行任何工作之前首先检查_isValid.

旁注:使用NSOperationQueue可能更合适.请参阅Chris Hanson的博客文章.


jos*_*hrl 8

关于这一点的一个有趣的事情是,如果提交给队列的块引用拥有队列的对象(例如"self"),则对象将不会被击中,dealloc直到队列中的所有待处理块都被完成.

这是一个演示这个的项目:

https://github.com/joshrl/GDCQueueDeallocTest