【问题标题】:Running a Cocoa GUI in a non-main thread在非主线程中运行 Cocoa GUI
【发布时间】:2012-04-03 10:52:48
【问题描述】:

我在开发可可用户界面时遇到了与 gui/线程相关的问题。应用程序是这样设计的:

主线程 (#1):解析参数、加载插件等

Gui 线程 (#?):启动 gui,处理事件等。它是 gui 线程。

Cocoa 框架是非线程安全的,但强制执行一条规则,GUI 必须在主线程上运行。断言用于检查这一点。为了解决这个问题,我自己实现了 run 方法(下面的代码),遵循这个 - http://cocoawithlove.com/2009/01/demystifying-nsapplication-by.html - 指南。但我错过了一些东西。一个窗口打开,但保持空白(完全白色)。虽然如果我在主线程中进行调用,它会完美运行。

所以基本上我需要弄清楚缺少什么。

- (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;
}

【问题讨论】:

  • 看起来你应该只反转你使用线程的东西。为什么要对抗框架?
  • 因为我宁愿不与程序的插件架构作斗争...但我想我将不得不承认这一点...

标签: objective-c multithreading macos cocoa user-interface


【解决方案1】:

在后台线程中执行所有操作,更新 GUI 除外。我看到您只有一行需要更新 GUI。所以按照你的方式去做,除了你在主线程中执行所有的 GUI 更新:

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

现在我不知道什么是 updateWindows,我认为这不会产生竞争条件。

【讨论】:

    【解决方案2】:

    为什么不扭转问题呢?让主线程产生一个线程(我们称之为应用程序线程),然后在产生 GUI 之前阻塞。应用线程将解析参数、加载插件等。初始化完成后,应用线程将向主线程发出信号以继续并启动 GUI。

    【讨论】:

      【解决方案3】:

      不要。这种方法永远行不通。即使您解决了当前的问题(窗口未绘制),您也会立即遇到另一个晦涩难懂的、无法解决的问题,还有一个,又一个。 Cocoa 期望 GUI 线程成为主线程,故事结束。

      【讨论】:

      • 想了很多,但我还是想试一试...谢谢您的回复。
      猜你喜欢
      • 2011-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-16
      • 1970-01-01
      • 2016-10-08
      • 1970-01-01
      相关资源
      最近更新 更多