2012-12-03 40 views
1

對於我面臨的情況,我有一個小問題。 我有2種方法:使用callback = concurrency執行選擇器?

- (void)firstSelector { 
    [self launchAsyncTask]; 
    ... do some work for a long time (10secs) ... 
} 

- (void)asyncTaskFinished { 
    ... some work after 5secs of async task ... 
} 

firstSelector執行launchAsyncTask這僅僅是有一個名爲asyncTaskFinished回調後臺任務。 假設firstSelector在啓動異步任務(假設爲10秒)後運行一段時間,並且異步任務運行5秒,是否會出現併發問題?

這是如何工作的? 將在firstSelector後執行asyncTaskFinished,否則firstSelector會暫停運行asyncTaskFinished

是否存在與運行循環的鏈接?方法被添加到一個隊列,然後執行,因爲我打電話給他們?

我迷路了:)

謝謝。

+0

您是否閱讀過文檔http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html?我相信它解釋了一切,直到你有任何具體的問題。 –

+0

據我所知,我的回調隊列使用主線程運行循環,但firstSelector呢?我使用標準的「[self firstSelector]」來執行它。它也是這樣排隊? –

+0

'回調'通常在與主'操作'相同的線程中被觸發,它可能是任何線程,而不僅僅是主線程。由於您沒有討論的代碼,通常可能的情況是'firstSelector'是從分離的線程中調用的,'launchAsyncTask'也會創建另一個後臺線程。或者它們可能與它們的主要/分離線程相同,或者它們中的一個在主線程中,另一個線程在分離的線程中。您也可能決定始終在主線程上觸發回調。這一切都是由設計驅動的,並且始終需要記錄良好,因爲每種情況都不相同。 –

回答

1

異步任務異步運行,不會在主循環中運行UI時在主運行循環中運行。看看Concurrency Programming Guide

因此,在您的情況下,您不確定同步時間需要多長時間。你假設它可能需要10秒,但它不完全確定。因此,在這種情況下,您需要使用block或在主線程完成異步任務時找到觸發asyncTaskFinished函數的方法。您可以定義一個簡單的塊回調,然後在異步任務完成時觸發該函數。

如果您使用GCD進行異步任務,它變得非常簡單。你會這麼做;

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     [self runMyAsyncTask]; 
     // trigger the main completion handler when this completed 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self asyncTaskFinished]; 
     }); 
    }); 

如果您使用NSThread進行併發處理,可以使用performSelector:onThread:在異步任務完成時觸發完成選擇器。對於一個簡單的例子,我會告訴你實現一個回調處理程序。你可以創建一個像這樣的函數來觸發異步任務,

-(void)launchAsyncTaskWithCompletionHandler:(void(^)(void))completionHandler{ 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     [self runMyAsyncTask]; 
     // trigger the main completion handler when this completed 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      completionHandler(); 
     }); 
    }); 
} 

並且調用這個比較簡單;

[self launchAsyncTaskWithCompletionHandler:^{ 
     [self asyncTaskFinished]; 
    }]; 

這很容易理解,使您的代碼更清晰。希望這可以幫助你。

+0

謝謝。我明白你寫的,已經知道這些概念。我遇到的問題發生在方法A運行並且來自另一實體的回調B在同一線程上調用(但方法A尚未完成)。如果兩種方法都使用運行循環排隊,那麼沒有問題(我認爲這是回調的情況,因爲我知道-performSelector ...使用運行循環)。 –

+0

但是在A沒有排隊的情況下(這是我不知道在使用[self methodA]時可可發生了什麼的情況下),它提出了一個問題(A正在執行,B將被執行,問題在於何時以及如何,因爲A不在隊列中)。 –

+0

@Nicolas請查看文檔中的「調度隊列任務」部分:https://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html它具有可用的串行/併發隊列的簡短說明。 –

0

線程的運行循環以順序(非併發)方式從其輸入源執行任務。因此,只要在同一個運行循環中執行firstSelectorasyncTaskFinished,就不必擔心。這將取決於回調語義。您可能需要使用類似performSelector:onThread:withObject:waitUntilDone:的內容來確保異步回調函數在正確的線程中執行。