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

时间:2011-04-01 08:20:54

标签: objective-c memory-management grand-central-dispatch

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

@property (nonatomic, assign) dispatch_queue_t queue;

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

-(void)dealloc
{
    dispatch_release(self.queue);
    self.queue = nil;
}

如何正确发布此内容?使用retain/release会有效吗?

如果在调用release时队列中有挂起/正在运行的东西会怎样?

4 个答案:

答案 0 :(得分:20)

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

  

派遣队列和其他派遣   对象是引用计数数据   类型。创建序列时   调度队列,它有一个初始   引用计数为1.您可以使用   dispatch_retain和dispatch_release   递增和递减的功能   根据需要引用计数。什么时候   队列的引用计数达到   零,系统是异步的   取消分配队列。

     

当您的申请不再需要时   调度队列,它应该释放   它与dispatch_release函数。   任何挂起的块提交给   queue保存对该队列的引用,   所以直到队列才被释放   所有待处理的块都已完成。

     

注意:您不需要保留或   发布任何全球派遣   队列,包括并发   调度队列或主要调度   队列。任何试图保留或   释放队列被忽略。

所以你可以在任何地方使用-retain使用dispatch_retain以及你会使用的任何地方-release使用dispatch_release。

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

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

旁注:使用NSOperationQueue可能更合适。见Chris Hanson的blog post

答案 1 :(得分:8)

有一点有趣的是,如果提交给队列的块引用拥有队列的对象(例如“self”),则在队列中的所有待处理块完成之前,对象将不会命中dealloc无论如何。

这是一个展示这一点的项目:

https://github.com/joshrl/GDCQueueDeallocTest

答案 2 :(得分:2)

设置你的财产:

@property (readwrite, strong, nonatomic) __attribute__((NSObject)) dispatch_queue_t queue;

分配是暗示的,强将保留队列告诉ARC将其视为NSObject。

答案 3 :(得分:1)

  

如果有东西会发生什么   等待/在队列上运行时   叫释放?

很安全。系统保留挂起/运行队列。调用dispatch_release只会影响队列的保留计数。请参阅dispatch_async的手册页等。