【问题标题】:NSRunAlertPanel() outside of the main thread?NSRunAlertPanel() 在主线程之外?
【发布时间】:2010-12-04 19:12:30
【问题描述】:

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

它几乎可以完美运行,但是有一个问题:处理产生了很多文件,如果这些文件中的一个或多个已经存在,我想在实际这样做之前询问用户是否可以覆盖它们。所以我尝试使用处理线程中的 NSRunAlertPanel()。

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

我想知道:除了使用计时器不断地从主线程轮询处理线程以了解它的进度之外,还有其他方法可以解决这个问题吗?

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

提前致谢。

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

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

然后在我的主线程上:

- (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];
    // ...
}

【问题讨论】:

    标签: objective-c cocoa multithreading


    【解决方案1】:

    主线程是 GUI 线程。你不应该在任何后台线程上做任何 GUI 东西。话虽如此,您可以编写一个调用NSRunAlertPanel() 的方法,然后使用NSObjectperformSelectorOnMainThread: 方法之一调用您的方法。

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

    【讨论】:

    • 更不用说,如果您不针对 10.3 下的任何内容,建议改用 NSAlert
    • 如果您要在主线程上执行某些操作,则无需检查您是否在主线程上。 performSelectorOnMainThread: 方法也可以在主线程中工作,更简单的代码更好。
    • 如果你将代码分派到已经在主线程上的主线程,我已经看到代码崩溃了。所以,我总是先检查。
    猜你喜欢
    • 2018-03-04
    • 1970-01-01
    • 2021-12-21
    • 1970-01-01
    • 2012-02-21
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多