I've stumbled upon a problem in the application I'm developing using cocoa. I need to do some processing, and I'm doing it on a separate thread. I'm doing this so I can display the progress using a NSProgressIndicator and not hang the main thread. (The user can cancel the execution if he/she wants).
It's almost working perfectly, But there's a problem: The processing produces a lot of files, and if one or more of these files already exists, I would like to ask the user if it's OK to overwrite them before actually doing so. So I tried using NSRunAlertPanel() from the processing thread.
It works some of the times. Other times, the Alert Panel will flicker, close for no particular reason before I can click on it, or not appear at all. So I figured that NSRunAlertPanel() is probably开发者_如何学Go not thread safe, and this is hapenning due to race conditions.
I would like to know: Is there a way I can fix this other than constantly polling the processing thread for it's progress from the main thread using a timer?
Is using the GUI from any thread other the main one inherently unsafe?
Thanks in advance.
EDIT: I'm following Marc's instructions but there's still something wrong, because my NSAlerts (which I'm also using now) are still disappearing. Here's my processing thread.
- (void)doProcess:(id)param
{
// ...
[self performSelectorOnMainThread:@selector(askForConfirmation) withObject:nil waitUntilDone:YES];
// ...
}
Then on my main thread:
- (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];
// ...
}
The main thread is the GUI thread. You should not do any GUI stuff on any background threads. That being said, you can write a method that calls NSRunAlertPanel()
and then call your method by using one of NSObject
's performSelectorOnMainThread:
methods.
To check if you are currently executing on the main thread, you can just call [NSThread isMainThread]
.
精彩评论