4

我在研究如何dispatch_async()的作品。dispatch_group_wait永遠等待

我想這個片段在main()

typedef void(^VoidBlock)(); 

VoidBlock aBlock = ^{ 
    NSLog(@"do work in main queue"); 
}; 
dispatch_async(dispatch_get_main_queue(), aBlock); 

但塊永遠不會被調用。我想也許主線程在塊運行之前結束。 然後我嘗試這樣的:

dispatch_group_t aGroup = dispatch_group_create(); 
VoidBlock aBlock = ^{ 
    NSLog(@"do work in main queue"); 
    dispatch_group_leave(aGroup); 
}; 
dispatch_group_enter(aGroup); 
dispatch_async(dispatch_get_main_queue(), aBlock); 
dispatch_group_wait(aGroup, DISPATCH_TIME_FOREVER); 

這不工作,要麼(塊不會被調用)。 區別在於現在主線程(正確)在語句上阻止了dispatch_group_wait(aGroup, DISPATCH_TIME_FOREVER)

問題是什麼?

+0

你的意思是你在'main.m'文件中試過這段代碼嗎? –

+0

是的,當然在'main.m'和裏面'main'功能! – drakon

+0

你在控制檯上查看輸出或使用斷點時嘗試了什麼? –

回答

4

我懷疑你沒有創建一個iOS的項目(或觸發runloop的任何其他項目類型),而是一個「命令行工具」。如果是這樣的話:

你的第一種方法

一般來說你的第一種方法是好的,但main()回報你的異步調用之前(因此你的應用程序運行完畢)是triggerd。

你的第二個方法

你在你的第二個方法有正確的觀念:等到你的異步工作已經完成。

儘管您的實現導致了死鎖。 wait阻塞從(主線程)調用的線程,直到塊完成運行,但該塊從不運行,因爲主線程被阻塞。

爲了解決這個問題,調度在不同的隊列比等待一個:

dispatch_group_t aGroup = dispatch_group_create(); 
VoidBlock aBlock = ^{ 
     NSLog(@"do work in main queue"); 
     dispatch_group_leave(aGroup); 
}; 
dispatch_group_enter(aGroup); 

// dispatch on another queue than the one wait will block 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), aBlock); 
dispatch_group_wait(aGroup, DISPATCH_TIME_FOREVER); 

這樣,主隊列正在等待(封端)和同時您的塊可以是(是)在另一個隊列上執行。


@Ishahaks answer創建一個「單一視圖應用程序」,而不是「命令行工具」也將工作(因爲這個問題原本功能標籤爲「iOS版」),即使在main()。原因是iOS應用程序觸發了一個runloop(while(true) { // wait for events }),所以應用程序在從main()返回後仍然運行。見Apples Runloop Documentation

+0

我以「命令行工具」創建了項目。爲什麼這是個問題?與其他隊列(不是主隊)類似的實驗效果很好! – drakon

+0

您沒有運行循環,因此應用程序在退出'main()'後已完成運行。不應該像'dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0)'這樣的其他隊列一起工作。 – shallowThought

+0

'dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0)'沒問題!問題在於主隊列。我想,因爲當主線程與'dispatch_group_wait'睡在一起時,主線程中不能再執行任何程序塊...... – drakon

0

如果您正在爲iOS開發,然後用「新」,「項目」,「單一視圖應用程序」,然後把你的代碼application:didFinishLaunchingWithOptions這樣的:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    // Override point for customization after application launch. 
    typedef void(^VoidBlock)(); 

    VoidBlock aBlock = ^{ 
     NSLog(@"do work in main queue"); 
    }; 
    dispatch_async(dispatch_get_main_queue(), aBlock); 
    return YES; 
} 
相關問題