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 создать "Single View Application" вместо "Tool Command Line" также будет работать (как вопрос был первоначально TAged как "прошивкой"), даже в 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

Если вы разрабатываете для прошивки, а затем использовать «Новый» «Проект» «Single View Application», затем поместить свой код в 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; 
} 
Смежные вопросы