Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running a Cocoa GUI in a non-main thread

I am having a gui/threading related problem in developing a cocoa user interface. The application is designed like this:

Main Thread (#1): parses arguments, loads plugins, etc.

Gui thread (#?): launches the gui, handles events, etc. Its the gui thread.

The Cocoa framework is non-thread safe, but enforces one rule, the GUI must run on the main thread. A assertion is used to check this. To try to go around this I implemented the run method myself (code below) following this - http://cocoawithlove.com/2009/01/demystifying-nsapplication-by.html - guide. But I am missing something. A window is opened, but stays blank (completely white). Although if I make the call in the main thread it works perfectly.

So basically I need to figure out what's missing.

- (void)run
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    [self finishLaunching];

    shouldKeepRunning = YES;
    do
    {
        [pool release];
        pool = [[NSAutoreleasePool alloc] init];

        NSEvent *event =
            [self
                nextEventMatchingMask:NSAnyEventMask
                untilDate:[NSDate distantFuture]
                inMode:NSDefaultRunLoopMode
                dequeue:YES];

        [self sendEvent:event];
        [self updateWindows];
    } while (shouldKeepRunning);

    [pool release];
}

- (void)terminate:(id)sender
{
    shouldKeepRunning = NO;
}
like image 879
OCarlos Avatar asked Mar 18 '12 20:03

OCarlos


2 Answers

Don't. This approach will never work. Even if you fix your current problem (the window not drawing) you'll immediately run into another obscure, impossible-to-fix problem, and another, and another. Cocoa expects the GUI thread to be the main thread, end of story.

like image 152
Kurt Revis Avatar answered Nov 11 '22 08:11

Kurt Revis


Do all in the background thread except updating the GUI. I see that you have only a line where you need to update the GUI. So do it the way you're doing it, except that you execute all GUI updates in the main thread:

dispatch_async(dispatch_get_main_queue(), ^
{
    [self updateWindows];
});

Now I don't know what's updateWindows, I assumed that this wouldn't create a race condition.

like image 2
Ramy Al Zuhouri Avatar answered Nov 11 '22 06:11

Ramy Al Zuhouri