NSRunLoop и GCD очереди - PullRequest
       42

NSRunLoop и GCD очереди

3 голосов
/ 02 марта 2011

Я создаю библиотеку c ++ для использования на iOS (да, к сожалению, это должен быть C ++), которая использует AVCaptureSession для захвата видеокадров, которые доставляются с помощью обратного вызова captureOutput. Библиотека C ++ - это мой продукт. У меня есть приложение Touch Touch для проверки / демонстрации. Итак, это выглядит так:

(тестовое приложение) <-----> (c ++ lib (обратные вызовы AVFoundation))

Тестовое приложение имеет элементы управления пользовательского интерфейса и отвечает практически за всю графику. Библиотека c ++ отображает фреймы в UIView через OpenGL.

Ты со мной? Хорошо


Хорошо, во-первых, пользователь нажимает кнопку UIB, которая делает вызов в мою библиотеку. Этот вызов занимает 10 секунд или более для завершения. Поэтому, если я помещу вызов непосредственно за нажатием кнопки, пользовательский интерфейс будет заблокирован до тех пор, пока не вернется функция библиотеки:

-(IBAction)hBut:(id)sender{
    [myLib foo]; // takes 10+ seconds to return
}

Это не хорошо. Следующее, что я попытался, это создать поток для вызова lib:

-(void)callIntoLib{
    [myLib foo];
}

-(IBAction)hBut:(id)sender{
    [NSThread detach..:myLib selector:foo object:nil];
}

Это больше не блокирует пользовательский интерфейс, но теперь функция обратного вызова видеокадров никогда не срабатывает (AVCaptureSession's captureOutput). Кажется, что основной NSRunLoop был заблокирован.

Затем я попробовал то же самое, но с Grand Central Dispatch:

-(IBAction)hBut:(id)sender{
     _myQueue = dispatch_queue_create("com.domain.me", NULL); // member variable
     dispatch_async(_myQueue,
     ^{
          [myLib foo];
     });
}

Это то же самое поведение. То есть обратный вызов для видеокадров не срабатывает. Lame

Почему основной NSRunLoop блокируется во 2-м и 3-м случаях? Есть ли способ связать с ним очереди?

Имеет ли это смысл?

Ответы [ 2 ]

2 голосов
/ 23 декабря 2011

Главный поток запускает свой runLoop сам по себе, поэтому события с камеры были доставлены в вашу библиотеку в первом случае. Пользовательские потоки не запускают runLoop, вы должны сделать это самостоятельно.

-(void)callIntoLib {
    [myLib foo];
    self.callIntoLibExecuted = YES;
}


-(void)threadBody {
    @autoreleasepool {
        self.callIntoLibExecuted = NO;

        [self performSelector:@selector(callIntoLib) 
                 onThread:[NSThread currentThread] 
                 withObject:nil
                 waitUntilDone:NO];

        while (!self.callIntoLibExecuted)
        {
           @autoreleasepool {
               [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
                         beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
           }
        }
    }
}

-(IBAction)hBut:(id)sender {
    [NSThread detachNewThreadSelector:@selector(threadBody) 
              toTarget:self withObject:nil];
}
0 голосов
/ 02 марта 2011

В этом примере кода используется только AVCaptureVideoDataOutput -setSampleBufferDelegate: queue: на GCDСерийная очередь.Кажется, что AVCaptureSession должен использоваться с RunLoop.Вам нужно выполнить собственный RunLoop в своем потоке или попытаться изменить свою библиотеку C ++ в качестве этого примера кода.

...