-1

I'm working on a program that would monopolize the main thread for its own purposes. Conditionally, this program may need to spawn Cocoa windows. However, because the main thread would not be running an event loop (or at least not a NSRunLoop), I was wondering if I would be able to run the UI with a NSRunLoop from a secondary thread.

I know the equivalent is possible on Windows, but it's not clear from the documentation if this would work on Mac OS, nor how to do it at all if it's possible.

For one thing, NSApplicationMain must be called by the main thread.

zneak
  • 134,922
  • 42
  • 253
  • 328
  • 1
    What's the advantage of running the GUI on a secondary thread and doing your work on the main thread, over the other way around? – Peter Hosey Mar 29 '13 at 07:11
  • When you feel that you've got to screw around with fundamental application design principles (on **any** platform) that's a *strong* indication that your whole design is flawed and you need to go back to the drawing board. – Jay Mar 29 '13 at 10:06
  • @Jay, please explain me why a GUI is _fundamentally_ supposed to be run from the main thread. This is absolutely doable on Windows and perfectly legit. With WPF and multiple app domains, you can even do it from multiple threads if that's your thing. In Java, Swing has its own thread, distinct from the main thread. If there's any fundamental flaw here, it's that Cocoa always looks for the first thread rather than the thread on which, say, `NSApplicationMain` was called, or the first run loop was created. – zneak Mar 29 '13 at 14:40
  • @PeterHosey, the program will have a GUI only if a specific library is loaded, and because the program interprets code from other sources, I can't let an inversion of control happen. My solution was to run the GUI on a secondary thread and use the `performSelector:onThread:` family of messages to synchronize between the interpreted code and the GUI. It would be prettier if the UI thread could have been encapsulated within the library that may need it and let the rest of my code be thread-independent. Instead, I'll probably have to spawn my own thread and let the main one sleep unless needed. – zneak Mar 29 '13 at 14:54
  • You can't split them into two programs, one of which starts the other and both of which use some IPC mechanism to communicate? – Peter Hosey Mar 29 '13 at 15:07
  • @PeterHosey, I thought about it but I'm a little concerned about the performance implications. This is for an application-level emulator for an old platform (kind of like Wine but for a discontinued OS), so I really can't do much about what the loaded app wants to do, I want it to be reasonably fast, and I would have liked it if I didn't need a special case for the UI lib. – zneak Mar 29 '13 at 15:10
  • You can do drawing across processes. Look into [IOSurface](http://developer.apple.com/library/mac/documentation/Miscellaneous/Reference/IOSurfaceAPI_header_reference/). From my brief look, you should be able to send the IOSurface to the emulator process via a Mach port or XPC message, then (in the emulator) create an OpenGL context or CGBitmapContext for it from its base address and other parameters. – Peter Hosey Mar 29 '13 at 15:20
  • This is definitely worth a good look. – zneak Mar 29 '13 at 15:56

1 Answers1

2

No. The UI needs to be on the main thread. You can do things in the background with NSOperation or other means and update the UI be doing performSelectorOnMainThread The UI itsel relies on the application run loop.

uchuugaka
  • 12,679
  • 6
  • 37
  • 55
  • I understand that it relies on the application run loop, but I don't see why that should be an issue. You can create a `NSRunLoop` on just any thread. – zneak Mar 29 '13 at 14:45
  • @zneak: Off the top of my head, there's the fact that Apple Events are delivered to the main thread's run loop. Opening a document in your app from (e.g.) the Finder, activating your app via the Dock, and “reopening” your app when the user launches it while it's already open are all Apple Events, and they *will* be delivered on the main thread, so AppKit's standard handlers must also be registered on the main thread. – Peter Hosey Mar 29 '13 at 15:12