2011-07-14 38 views
2

我使用GCD從互聯網上進行一些背景加載。除了一點缺陷之外,這個工作很好。在我的應用程序中,我有3個選項卡,當點擊任何選項卡時,GCD開始爲適當的選項卡執行後臺加載。如果用戶決定從第一個標籤頁到第二個標籤頁(當GCD開始下載第一個標籤頁的數據時),然後再次返回到第一個標籤頁。 GCD將啓動另一個後臺線程(即使第一個後臺線程尚未完成下載數據)。使用Grand Central Dispatch,如何檢查是否有塊正在運行?

那麼有沒有辦法來檢查後臺線程當前是否正在運行?因此,如果用戶選擇非常快速地來回切換標籤(由於某種原因),它不會啓動多個後臺線程。

+0

「GCD將啓動另一個線程」。其實我認爲你告訴GCD開始另一個線程。你需要某種標誌來表明線程正在運行。在塊的開始位置設置爲true,在末尾設置爲false。我相信對bool的讀/寫是一種內在的。 –

回答

9

如果您想防止同時運行兩個相同類型的塊,則可以使用調度信號量。信號量設置爲1時,您可以在發射塊之前檢查信號量,並在有些事情仍在運行時保釋。在該塊的結尾處,您發出信號燈以允許提交其他塊。

我在我的一個應用程序中這樣做,以防止一次將多個OpenGL ES幀渲染塊添加到隊列中(如果幀長度超過1/60秒,防止在隊列中累積塊渲染)。我介紹一些這在我的答案here,使用下面的代碼:

if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0) 
{ 
    return; 
} 

dispatch_async(openGLESContextQueue, ^{ 

    [EAGLContext setCurrentContext:context]; 

    // Render here 

    dispatch_semaphore_signal(frameRenderingSemaphore); 
}); 

其中前面創建frameRenderingSemaphore如下:

frameRenderingSemaphore = dispatch_semaphore_create(1); 

如果您創建的每個選項卡的下載操作了類似的信號,你可以進行檢查以確保多個下載不會在該選項卡上一次排隊。

0

你需要的是一個簡單的布爾標誌,以避免再次啓動任務,直到它完成(根本不涉及GDC)。類似的信息(僞代碼,沒有測試,聲明等):

- (void)something_you_run_in_your_view_did_appear 
{ 
    synchronize(self) { 
     if (self.doing_task) 
      return; 
     self.doing_task = YES; 
    } 
    start_your_task_here 
} 

- (void)something_you_run_when_the_task_finishes 
{ 
    synchronize(self) { 
     self.doing_task = NO; 
    } 
} 

這個僞代碼將工作的事情就像一個異步NSURLConnection的。我還沒有探索GDC,其他人將需要適應GDC(你自己?)。

請注意,在這個例子中,我使用的是一個屬性而不是簡單的變量訪問。這允許您在setter中實現更有趣的事情,例如激活活動指示器,禁用用戶界面輸入等。當變量的狀態在父類中變化時,它也可以與他們的事的子類一起使用。

+1

只是不在線程安全的訪問器中執行任何操作。 –

相關問題