значение переменной __block не меняется

Приведенный ниже код будет асинхронно загружать значение актива. Я жду его, используя цикл while.

    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:aAudioLink options: nil];
    [asset loadValuesAsynchronouslyForKeys:keys 
                 completionHandler:^{                                           
                canExit = TRUE;
                         }];

    while (canExit == FALSE) {
        // NSLog (@"canExist = FALSE");     
    }

    NSLog(@"canExist = TRUE");

Если оператор NSLog прокомментирован, как код выше, последний NSLog не будет вызываться. Если оператор NSLog НЕ прокомментирован, вызывается последний NSLog.

Блок и код вне блока выполняются в разных потоках, и оба они не являются основным потоком.

В чем причина этого?


person BB.    schedule 03.01.2013    source источник
comment
прежде всего, вы никогда не должны этого делать, это полностью противоречит цели асинхронности метода. Во-вторых, это зависит от того, как объявлен canExit. Блоки обрабатывают переменные по-другому, вы можете передавать их либо как копию, либо как адрес, и они также зависят от области видимости. И в-третьих, я считаю, что проблема заключается в том, что ваш код может быть оптимизирован компилятором, без этого nslog он может подумать, что это неуместный вызов, и может его убрать. Это всего лишь дикая догадка, поэтому я добавляю ее в качестве комментария = p   -  person Pochi    schedule 03.01.2013


Ответы (1)


Я думаю, что вы не должны использовать цикл while для этого. Недавно я имел дело с приложением, в котором мне пришлось использовать AVAsset для создания эскиза изображения для актива. В итоге я использовал семафор диспетчеризации для блокировки потока, пока изображение не будет сгенерировано асинхронно.

Почему нельзя попробовать следующее.

 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

 AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:aAudioLink options: nil];

dispatch_async(queue, ^{

[asset loadValuesAsynchronouslyForKeys:keys 
             completionHandler:^{                                           
            canExit = TRUE;
            dispatch_semaphore_signal(sema);
             }];
    });



dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
dispatch_release(sema);

Должно сработать, если я прав.

person Xcoder    schedule 03.01.2013