Запуск графического интерфейса Какао в неосновном потоке

У меня возникла проблема с GUI / Threading при разработке пользовательского интерфейса какао. Приложение разработано так:

Основной поток (#1): анализирует аргументы, загружает плагины и т. Д.

Поток графического интерфейса (#?): Запускает графический интерфейс, обрабатывает события и т. Д. Это поток графического интерфейса.

Каркас Какао не является потокобезопасным, но применяет одно правило: графический интерфейс должен выполняться в основном потоке. Утверждение используется, чтобы проверить это. Чтобы попытаться обойти это, я сам реализовал метод run (код ниже), следуя этому - http://cocoawithlove.com/2009/01/demystifying-nsapplication-by.html - руководству. Но я что-то упустил. Окно открывается, но остается пустым (полностью белым). Хотя, если я сделаю звонок в главном потоке, он отлично работает.

В общем, мне нужно выяснить, чего не хватает.

- (void)run
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    [self finishLaunching];

    shouldKeepRunning = YES;
    do
    {
        [pool release];
        pool = [[NSAutoreleasePool alloc] init];

        NSEvent *event =
            [self
                nextEventMatchingMask:NSAnyEventMask
                untilDate:[NSDate distantFuture]
                inMode:NSDefaultRunLoopMode
                dequeue:YES];

        [self sendEvent:event];
        [self updateWindows];
    } while (shouldKeepRunning);

    [pool release];
}

- (void)terminate:(id)sender
{
    shouldKeepRunning = NO;
}

3 ответа

Не. Этот подход никогда не сработает. Даже если вы исправите свою текущую проблему (окно не рисует), вы сразу же столкнетесь с другой неясной проблемой, которую невозможно исправить, и другой, и другой. Какао ожидает, что поток GUI будет основным, конец истории.

Делайте все в фоновом потоке, кроме обновления GUI. Я вижу, что у вас есть только строка, где вам нужно обновить графический интерфейс. Так что делайте так, как вы делаете, за исключением того, что вы выполняете все обновления GUI в основном потоке:

dispatch_async(dispatch_get_main_queue(), ^
{
    [self updateWindows];
});

Теперь я не знаю, что такое updateWindows, я предположил, что это не создаст условия гонки.

Почему бы не решить проблему? Сделайте так, чтобы основной поток порождал поток (назовем это потоком приложения), а затем блокировал перед созданием графического интерфейса. Поток приложения будет анализировать аргументы, загружать плагины и т. Д. После завершения инициализации поток приложения будет сигнализировать основному потоку о необходимости запуска и запуске графического интерфейса.

Другие вопросы по тегам