NSRunAlertPanel () вне основного потока? - PullRequest
4 голосов
/ 08 октября 2009

Я наткнулся на проблему в приложении, которое я разрабатываю с использованием какао. Мне нужно сделать некоторую обработку, и я делаю это в отдельном потоке. Я делаю это, чтобы я мог отображать прогресс, используя NSProgressIndicator, а не вешать основной поток. (Пользователь может отменить выполнение, если он / она хочет).

Это почти идеально работает, но есть проблема: при обработке создается много файлов, и если один или несколько из этих файлов уже существуют, я хотел бы спросить пользователя, можно ли их перезаписать, прежде чем это сделать. Поэтому я попытался использовать NSRunAlertPanel () из потока обработки.

Это работает иногда. В других случаях панель предупреждений будет мигать, закрываться без особой причины, прежде чем я смогу нажать на нее, или не появиться вообще. Поэтому я решил, что NSRunAlertPanel (), вероятно, не является потокобезопасным, и это происходит из-за условий гонки.

Я хотел бы знать: есть ли способ исправить это, кроме как постоянно опрашивать поток обработки для его прохождения из основного потока, используя таймер?

Является ли использование графического интерфейса пользователя из любого другого потока основным по своей сути небезопасным?

Заранее спасибо.

РЕДАКТИРОВАТЬ: Я следую инструкциям Марка, но все еще что-то не так, потому что мои NSAlerts (которые я также использую сейчас) все еще исчезают. Вот мой поток обработки.

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

1 Ответ

4 голосов
/ 08 октября 2009

Основной поток - поток GUI. Вы не должны делать какие-либо вещи GUI на каких-либо фоновых потоков. При этом вы можете написать метод, который вызывает NSRunAlertPanel(), а затем вызвать ваш метод, используя один из NSObject performSelectorOnMainThread: методов.

Чтобы проверить, выполняете ли вы в данный момент основной поток, вы можете просто позвонить [NSThread isMainThread].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...