2012-01-11 68 views
2

我有一個以編程方式創建NSWindow + NSView的基於Cocoa的命令行應用程序。它使用nextEventMatchingMask循環手動抽取事件循環和調度事件。這個循環被一些高級代碼週期性地調用來輪詢輸入。從後臺線程中抽取可可消息循環

如果我在主線程上運行所有東西,那麼這個工作正常,視圖正確接收輸入事件。

如果我將窗口創建和消息循環移動到單獨的線程,則nextEventMatchingMask不再返回任何事件,並且視圖不會接收輸入。

我知道只有Cocoa應用中的「主」線程應該處理事件。然而,這個輔助線程是唯一需要與Cocoa交談的線程,所以我想將它用作Cocoa所關注的「主」線程。這可能嗎?我從這個線程調用了NSApplicationLoad,並且據我所知這是在這個過程中調用的第一個Cocoa函數。

如果我不能指定哪一個是主Cocoa線程,那麼有沒有其他方法能夠在後臺線程上創建NSWindow並接收它的事件?我不能做類似於調用NSApplication Run的事情,因爲我沒有控制應用程序的主循環。當上層代碼請求我這樣做時,我只需要從Window中提取輸入事件。

+0

此:http://stackoverflow.com/questions/6178618/mac-os-x-is-it-possible-to-imbue-a-non -main-thread-to-become-the-main-thread聽起來和我的情況完全一樣。 – eodabash 2012-01-11 02:28:12

回答

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 2012-01-11 19:01:19

1

這不是我會依賴的行爲。

如果您需要在不受運行循環限制的線程上運行後端,請在輔助線程上運行它以便從主線程運行UI。

或者,你可以創建另一個進程......