Domanda

Ecco una versione semplificata del mio codice:

- (IBAction)convert:(id)sender
{
    /* these two lines are ignored */
    [textbox setStringValue:@"converting"];
    [convertButton setEnabled:NO];

        pid_t pid;
        if((pid=fork())==-1)
        {
            [log setStringValue:@"couldn't fork a new process."];
            converting = 0;
        [convertButton setEnabled:YES];
            return;
        }else if (pid==0)
        {
            //this is the child
            sleep(2);
            exit(0);
        }else{
            int status;
            waitpid(pid,&status,0);
        }
    }
}

È una chiamata fork () piuttosto semplice. Il problema è che le due righe in alto (contrassegnate da un commento) vengono ignorate ... non sembrano essere eseguite fino a quando dopo il figlio biforcuto esce. Perché?

Modifica : e cosa posso fare per risolverlo?

È stato utile?

Soluzione

Davvero davvero davvero non vuoi chiamare fork () in un'applicazione Cocoa. Ci sono circa un miliardo di gotcha diversi nel farlo, principalmente legati al modo in cui varie risorse come le porte mach e altre infrastrutture di legame del sistema sopravvivono oltre il limite fork () . Le discussioni causano anche tutti i tipi di inferno.

Usa invece NSTask . Mentre esegue efficacemente fork () / exec () internamente, lo fa con molta cura per assicurarsi che sia fatto correttamente.

Altri suggerimenti

Forse perché il codice deve tornare al ciclo degli eventi principale prima che la GUI possa cambiare stato? Oppure, una leggera variazione, perché il thread che esegue la GUI è bloccato mentre il codice sta eseguendo un'attesa a livello di kernel ()?

bbum ha capito bene. Ecco il codice che ho finito per usare:

- (IBAction)convert:(id)sender
{
    task = [[NSTask alloc] init];
    [task setLaunchPath: @"/usr/local/bin/lame"];

    NSArray *arguments;
    arguments = [NSArray arrayWithObjects: file,outputFile, nil];
    [task setArguments: arguments];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskFinished:) name:NSTaskDidTerminateNotification object:task];

    [task launch];  
}
- (void) taskFinished:(NSNotification *)note {
    // code here executes after process finishes    
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top