2012-01-11 69 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。

或者,你可以创建另一个进程......