从背景螺纹抽的可可粉消息圈

时间:2012-01-11 01:19:24

标签: macos cocoa

我有一个基于Cocoa的命令行应用程序,它以编程方式创建NSWindow + NSView。它使用nextEventMatchingMask循环手动泵送事件循环和调度事件。一些高级代码会定期调用此循环以轮询输入。

如果我在主线程上运行所有内容,那么这可以正常工作,因为视图可以正确接收输入事件。

如果我将窗口创建和消息循环移动到单独的线程,则nextEventMatchingMask不再返回任何事件,并且视图不接收输入。

我知道只有Cocoa应用程序中的“主”线程才能处理事件。然而,这个辅助线程是唯一需要与Cocoa通信的线程,因此就Cocoa而言,我想将它用作“主”线程。这可能吗?我从这个线程调用NSApplicationLoad,据我所知这是该过程中调用的第一个Cocoa函数。

如果我不能指定哪个是主Cocoa线程那么,有没有其他方法可以在后台线程上创建NSWindow并为其接收事件?我无法执行类似调用NSApplication Run的操作,因为我无法控制应用程序的主循环。当上层代码请求我这样做时,我只需要从Window中提取输入事件。

2 个答案:

答案 0 :(得分: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)。希望这至少可以为你提供另一条途径。

答案 1 :(得分:1)

这不是我依赖的行为。

如果需要在不受运行循环限制的线程上运行后端,则在辅助线程上运行它,以便从主线程运行UI。

或者,您可以创建另一个流程......