NSRunAlertPanel() 在主线程之外?

Mar*_*lio 4 cocoa multithreading objective-c

我在使用可可开发的应用程序中偶然发现了一个问题。我需要做一些处理,并且我在一个单独的线程上进行。我这样做是为了可以使用 NSProgressIndicator 显示进度,而不是挂起主线程。(如果用户愿意,可以取消执行)。

它几乎工作完美,但有一个问题:处理过程会产生大量文件,如果这些文件中的一个或多个已经存在,我想询问用户是否可以在实际执行此操作之前覆盖它们。所以我尝试从处理线程使用 NSRunAlertPanel() 。

有时它会起作用。其他时候,警报面板会闪烁,在我点击它之前无特殊原因关闭,或者根本不出现。所以我认为 NSRunAlertPanel() 可能不是线程安全的,这是由于竞争条件而发生的。

我想知道:除了使用计时器不断轮询处理线程以了解主线程的进度之外,还有什么方法可以解决此问题?

从主线程以外的任何线程使用 GUI 本质上是不安全的吗?

提前致谢。

编辑:我正在按照马克的指示进行操作,但仍然有问题,因为我的 NSAlerts (我现在也在使用)仍然消失。这是我的处理线程。

- (void)doProcess:(id)param
{
    // ...
    [self performSelectorOnMainThread:@selector(askForConfirmation) withObject:nil waitUntilDone:YES];
    // ...
}
Run Code Online (Sandbox Code Playgroud)

然后在我的主线程上:

- (void)askForConfirmation
{
    [[NSAlert alertWithMessageText:@"Test." defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:@"Testing."] runModal];
}

- (IBAction)startProcessing:(id)sender
{
    // ...
    [NSThread detachNewThreadSelector:@selector(doProcess:) toTarget:self withObject:nil];
    // ...
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*c W 5

主线程是GUI线程。您不应该在任何后台线程上执行任何 GUI 操作。话虽这么说,您可以编写一个调用的方法NSRunAlertPanel(),然后使用其中一个方法来调用您的NSObject方法performSelectorOnMainThread:

要检查当前是否正在主线程上执行,只需调用[NSThread isMainThread].

  • 如果要在主线程上执行某些操作,则无需检查是否在主线程上。“performSelectorOnMainThread:”方法也可以在主线程中工作,并且代码越简单越好。 (2认同)