2011-04-01 43 views
18

我使用的是通過其擁有的屬性訪問的dispatch_queue,像這樣:什麼是釋放GCD調度隊列屬性的正確方法?

@property (nonatomic, assign) dispatch_queue_t queue; 

注意assign關鍵字。隊列在整個對象生命中都被使用,因此被對象所擁有。當擁有的對象被釋放時,我釋放隊列:

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

如何正確釋放此?將使用retain/release工作?

如果在調用發佈時隊列正在等待/運行在隊列中,會發生什麼情況?

回答

19

以下是從顯影劑文檔被盜:

調度隊列和其他調度 對象引用計數數據 類型。當您創建一個序列號 調度隊列時,它的初始參數爲 。您可以使用 dispatch_retain和dispatch_release 函數來根據需要遞增和遞減 引用計數。當 隊列的引用計數達到 爲零時,系統異步 解除分配隊列。

當你的應用程序不再需要 的調度隊列時,它應該用dispatch_release函數釋放它 。 提交給 隊列的任何掛起的塊保留對該隊列的引用, 因此隊列不會被釋放,直到 所有掛起的塊都完成。

注意:您不需要保留或釋放 任何全局調度 隊列,包括併發 調度隊列或主調度 隊列。任何試圖保留或釋放隊列的操作都會被忽略。

所以你會使用任何地方 - 請使用dispatch_retain和任何你會使用的地方 - 請使用dispatch_release。

調度隊列遵循與objective-c對象相同的一般內存管理約定。直到排隊的所有塊完成後,它們纔會被釋放。

如果您確實需要關閉調度隊列的方法:無法通過任何類型的API取消所有入隊的塊,因此它們必須始終運行完成。加快這一過程的一種方法是在管理調度隊列的類中有一個BOOL變量:_isValid。當你想關閉隊列時,你可以設置_isValid爲NO。提交給隊列的所有塊應該在做任何工作之前首先檢查_isValid。

A side comment:使用NSOperationQueue可能更合適。見Chris Hanson的blog post

+1

當然,如果您在dealloc中設置了類中的_isValid,則該對象將被銷燬,這意味着_isValid無法再安全讀取 - 這是什麼方法? – CiscoIPPhone 2012-07-27 17:18:38

+1

其實它似乎調用dispatch_group_wait會完全避免這個問題。 – CiscoIPPhone 2012-07-27 17:23:01

+1

@CiscolPPhone「對象將被銷燬」 - 實際上,不會訪問塊內的屬性會增加其保留計數,因此即使在執行dealloc之後,它仍會保留在塊的完成之前?我一直在這樣做,所以我通常只引用塊中的弱屬性(在我創建'__weak MyClass weakSelf = self'之前,然後在塊中使用weakSelf.property。然後如果塊在執行dealloc之後執行它只是命中一個零weakSelf.property&安全地死亡。) – jankins 2013-04-03 17:22:41

1

如果有東西 掛起/隊列運行時調用 釋放,會發生什麼?

這是安全的。掛起/運行隊列從系統中保留。調用dispatch_release只會影響隊列的保留計數。請參閱dispatch_async的手冊頁等。

7

有一個有趣的事情是,如果提交給隊列的塊引用擁有該隊列的對象(例如「self」),則該對象將不會擊中dealloc,直到隊列中的所有待處理塊都完成。

下面是一個說明這個項目:

https://github.com/joshrl/GDCQueueDeallocTest

2

設置你的財產,像這樣:

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

分配是隱含的和堅強的意志保留隊列告訴ARC把它當作一個NSObject的。

相關問題