19

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

@property (nonatomic, assign) dispatch_queue_t queue;

注意assign关键字。队列在对象的整个生命周期中使用,因此归对象所有。当拥有对象被释放时,我释放队列:

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

我如何正确释放这个?会使用retain/release工作吗?

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

4

4 回答 4

22

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

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

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

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

因此,在任何使用 -retain 的地方都使用 dispatch_retain,在任何使用 -release 的地方都使用 dispatch_release。

调度队列遵循与objective-c 对象相同的通用内存管理约定。在所有排队的块完成之前,它们不会被释放。

如果您确实想要一种关闭调度队列的方法:无法通过任何类型的 API 取消所有排队的块,因此它们始终必须运行到完成。加快此过程的一种方法是在管理调度队列的类中有一个 BOOL 变量:_isValid。当您想关闭队列时,您可以将_isValid 设置为NO。所有提交到队列的块在做任何工作之前都应该首先检查_isValid。

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

于 2011-04-01T09:17:23.710 回答
8

一件有趣的事情是,如果提交给队列的块引用了拥有队列的对象(例如“self”),那么dealloc在队列中的所有未决块无论如何都完成之前,该对象将不会命中。

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

https://github.com/joshrl/GDCQueueDeallocTest

于 2012-01-16T20:33:53.477 回答
2

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

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

于 2011-04-01T09:52:12.480 回答
2

像这样设置你的财产:

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

分配是隐含的,Strong 将保留告诉 ARC 将其视为 NSObject 的队列。

于 2012-09-13T00:44:30.777 回答