2012-01-11 2 views
2

У меня есть приложение командной строки на основе какао, которое программно создает NSWindow + NSView. Он использует цикл nextEventMatchingMask для ручной перекачки событий и событий отправки. Этот цикл вызывается некоторым кодом верхнего уровня для опроса для ввода.Накачка конвейера какао из фоновой темы

Если я запустил все в основном потоке, это прекрасно работает, поскольку представление правильно принимает входные события.

Если вместо этого я перемещаю окно создания и цикл сообщений в отдельный поток, то nextEventMatchingMask больше не возвращает никаких событий, и представление не получает вход.

Я знаю, что только «основная» нить в приложении Cocoa должна обрабатывать события. Этот вторичный поток, однако, является единственным потоком, который должен говорить с Cocoa, поэтому я хотел бы использовать его как «основную» нить, насколько это касается Cocoa. Это возможно? Я вызываю NSApplicationLoad из этого потока, и насколько я знаю, это первая функция Cocoa, вызываемая в этом процессе.

Если я не могу указать, что является основным потоком какао, тогда есть ли другой способ создать NSWindow в фоновом потоке и получить для него события? Я не могу сделать что-то вроде вызова NSApplication Run, потому что я не контролирую основной цикл приложения. Мне просто нужно вывести события ввода из окна, когда код верхнего уровня запрашивает, что я это делаю.

+0

Это: http://stackoverflow.com/questions/6178618/mac-os-x-is-it-possible-to-imbue-a-non -main-thread-to-станет-main-thread звучит точно так же, как и моя ситуация. – eodabash

ответ

3

Возможно, вам нужно запустить runloop на вторичной резьбе. В основном потоке, когда нерест свой вторичный поток, называют что-то вроде этого:

[NSThread detachNewThreadSelector:@selector(launchThread) 
         toTarget:[ThreadHandler class] 
         withObject:nil]; 

В классе ThreadHandler, есть что-то вроде:

+ (void)launchThread 
{ 
    NSRunLoop *threadRunLoop = [NSRunLoop currentRunLoop]; 
    while (someThreadExitCondition && [threadRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1]]); 
} 

Это должно начать свою нить событий обработки runloop. Я не уверен, не проверяя, позволит ли это вам обрабатывать события для окна, созданного во вторичном потоке, но вы можете начать с того, как запустить runloop потока. Вы могли бы даже создать нечто вроде ситуации с распределенными объектами, в которой вы накачиваете события из основного цикла событий через NSConnection во вторичный поток (example). Надеюсь, это может по крайней мере дать вам еще один путь для продолжения.

+0

Спасибо за предложение. Однако дополнительная морщина заключается в том, что эта вторичная нить, о которой идет речь, представляет собой нить posix, а не NSThread и не управляется мной. Он периодически вызывает код, над которым я работаю, когда он хочет, чтобы я проверял события, поэтому я не могу войти в какой-либо цикл цикла блокировки. Возможно, я могу попытаться развернуть свой поток обработки событий, как вы описали, а затем каким-то образом маршали обработанные события (при условии, что я могу их получить) обратно в поток, который считает, что он выполняет обработку события. – eodabash

1

Это не поведение, на которое я бы положился.

Если вам нужно запустить свой сервер в потоке, который не ограничен циклом запуска, затем запустите его на вторичном потоке, чтобы запустить пользовательский интерфейс из основного потока.

В качестве альтернативы, вы можете создать еще один процесс ...

Смежные вопросы