Mac OS X:是否有可能让非主线程成为进程的“主线程”?

18
我在Mac OS X(10.6.7)下遇到了与GUI/线程相关的问题。 我正在使用wxWidgets框架(版本2.9.1),并且在我的案例中,它基于Cocoa。应用程序设计如下:
  • 线程#1(也称为“主线程”):输入main(),解析开关,如果必要,在另一个线程中启动(使用POSIX原语)
  • 线程#2(也称为“GUI线程”):使用wxEntry初始化wxWidgets并显示GUI。

与大多数其他GUI框架一样,Cocoa不是线程安全的,因此我们确保从线程#2中进行所有GUI调用,必要时传递消息。 然而,在这种情况下,Cocoa的内部会在初始化期间(更准确地说,来自NSUndoManager)引发断言,指出“在主线程之外使用我不安全”。即使线程#2作为任何与GUI相关的内容方面的主线程。

好吧,NSUndoManager必须有一种方法来找出它正在运行的是否是主线程(可能使用NSThread::isMainThread())。所以我的问题是:是否可能欺骗NSUndoManager(和Cocoa通常)关于此事?甚至更好的是,将线程#2声明为“主线程”,线程#1成为次要的?基本上,我需要一个API调用,例如“使调用线程成为主要线程”。文档未知的巫术和Objective C++是可以接受的,只要它在OS X 10.5上也可以运行。

附:现有代码在Windows/Linux/MacOSX+Carbon下均可无缺地运行。此外,重新设计以更改线程结构将是一件非常麻烦的事情。


2
线程#1在应用程序的生命周期中正在做什么? - John
2
[NSThread isMultiThreaded] 返回 YES 吗?你需要使用 NSThread 至少生成一个线程,才能让 Cocoa 开启多线程支持。 - LaC
1
你为什么不使用主线程处理 GUI,而将其他工作交给其他线程? - wilx
1
@John,线程#1会生成一些其他线程,并在某种事件循环中等待事件。它基本上组织了所有事情。@LaC,谢谢你的指针,我会去看看的。@wilx,正如我所说,我可以使用主线程来处理GUI,但这将需要进行大量的重新设计,因为在我们的情况下,GUI是可选的 - 可能不需要,但应用程序仍然可能需要执行所有其他工作。实质上,GUI仅用于可视化正在进行的工作。 - anrieff
我不知道是什么实现细节导致了这种情况,但我记得曾经在Mac OS上采取你正在做的方式(在一个不同于调用“main”的线程中运行GUI和事件循环),系统库会非常混乱。就像,在第一个与GUI相关的调用处崩溃或死锁。我建议你想办法从“main”中调用自己。如果您的应用程序设计得很好,我不确定为什么这会是一个“巨大的痛苦”,所以我鼓励您更加深入地思考。结果将比热补丁Cocoa或其他一些hackery更好。 - asveikau
1个回答

1

好的,根据您的评论:您基本上无法避免重构代码。大多数GUI系统使用主线程并为自己处理事件循环。但是,如果您说GUI是可选的,也许最好将应用程序拆分为两个部分--工作程序和GUI。GUI可以通过多种方式与工作程序通信,具体取决于平台/特定需求。


2
顺便说一下,wxWidgets的开发人员已经向我保证,就wxWidgets而言,调用wxEntry()的线程是主线程,这使得您可以在程序内使用任意线程结构,只要所有GUI处理都在一个线程内完成(至少Win32 API、GTK甚至OS X上的Carbon允许您这样做)。然而,Cocoa强制执行这个特定的限制,因此我在这里发布了这个问题。所以,我有点放弃重新设计我的代码的前景。但当然,如果有一个简单快捷的方法可以解决问题,那将会更好... - anrieff
@LaC,isMultiThreaded返回“yes”,我已经按照此处描述的方式保护了Cocoa框架here - anrieff
3
你可以在应用程序的生命周期开始时创建新线程,在新线程中调用旧的 main(),然后不再创建“GUI线程”,而是将主线程用作GUI线程。 - John

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接