Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 多线程中带有信号量的NSTask卡在waitUntilExit中_Objective C_Multithreading_Cocoa_Semaphore_Nstask - Fatal编程技术网

Objective c 多线程中带有信号量的NSTask卡在waitUntilExit中

Objective c 多线程中带有信号量的NSTask卡在waitUntilExit中,objective-c,multithreading,cocoa,semaphore,nstask,Objective C,Multithreading,Cocoa,Semaphore,Nstask,我的Cocoa应用程序有多个线程(最多8个线程),使用NSTask运行python脚本,大约需要1200秒。几乎在运行NSTask的8个线程的每次执行中,应用程序都会一直等待,而且永远不会返回。我暂停了执行,注意到应用程序卡在waitUntilExit中。 我的代码片段如下所示。请帮助让我知道如何解决这个问题 dispatch_semaphore_t MySemaphore; 首先,您不需要重复调用[filehandlewaitfordatainbackgroundandnotify

我的Cocoa应用程序有多个线程(最多8个线程),使用NSTask运行python脚本,大约需要1200秒。几乎在运行NSTask的8个线程的每次执行中,应用程序都会一直等待,而且永远不会返回。我暂停了执行,注意到应用程序卡在waitUntilExit中。 我的代码片段如下所示。请帮助让我知道如何解决这个问题

  dispatch_semaphore_t MySemaphore;


首先,您不需要重复调用
[filehandlewaitfordatainbackgroundandnotify]。可能不是你问题的根源

其次,在这种情况下,几乎总是因为缓冲问题。但你已经解决了这个问题。第二个最常见的原因是任务没有终止


您确定python脚本实际上正在终止吗?

是的,我确定python脚本正在终止。您还建议我做什么来解决nstask waituntilexit中的“永远等待”问题?@user2370312除了确保从输出管道读取所有数据之外,我不确定。我在想,还有什么会阻止终止协议,结果是一片空白。
MySemaphore = dispatch_semaphore_create(8);
//Code portion where NSTask is used to execute a python script.
...
NSTask* task = [NSTask new];

    [task setLaunchPath:launchPath];
    [task setArguments:[NSArray arrayWithObjects:param1,
                                param2, param3,
                                param4, param5,
                                param6, param7, nil]];
    NSData *outData;
    NSData *errorData;
    int retVal;


         dispatch_semaphore_wait(MySemaphore, DISPATCH_TIME_FOREVER);

        retVal = [self _runTask:task
                             inData:nil
                            outData:&outData
                          errorData:&errorData];
        dispatch_semaphore_signal(MySemaphore);

    NSMutableString *retStr = [[[NSMutableString alloc] initWithData:outData
                                                                 encoding:NSUTF8StringEncoding] autorelease];
    NSMutableString *retStrErr = [[[NSMutableString alloc] initWithData:errorData
                                                                       encoding:NSUTF8StringEncoding] autorelease];

        if([retStrErr length] != 0)
        {
            [retStr appendString:@"\nstandard Error output:\n"];
            [retStr appendString:retStrErr];
        }

        if( retVal == 0 )
        {
            [retStr appendString:@"\nOK\n"];

        }
        else
        {
            [retStr appendString:@"\nERROR\n"];
        }

        NSLog(@"Response of _DRAMRetention for UUT:%d, %@", nUut+1, retStr);

        [task release];
- (int) _runTask:(NSTask*)task inData:(NSData*)inData outData:(NSData**)outData errorData:(NSData**)errorData
{
    NSPipe*             inPipe = nil;
    NSPipe*             outPipe = nil;
    NSPipe*             errorPipe = nil;
    NSFileHandle*       fileHandle;

    /* Reset output variables */
    if(outData)
    {
        *outData = nil;
    }

    if(errorData)
    {
        *errorData = nil;
    }
    /* Safe check */
    if(task == nil)
    {
        return -1;
    }
    /* Create standard input pipe */
    if([inData length])
    {  
        if((inPipe = [NSPipe new]))
        {
            [task setStandardInput:inPipe];
            [inPipe release];
        }
        else
        {
            task = nil;
            goto Exit;
        }
    }

    /* Create standard output pipe */
    if(outData)
    {
        if((outPipe = [NSPipe new]))
        {
            [task setStandardOutput:outPipe];
            [outPipe release];
        }
        else
        {
            task = nil;
            goto Exit;
        }
    }

    /* Create standard error pipe */
    if(errorData)
    {
        if((errorPipe = [NSPipe new]))
        {
            [task setStandardError:errorPipe];
            [errorPipe release];
        }
        else
        {
            task = nil;
            goto Exit;
        }
    }

    /* Launch task */
    NS_DURING
    [task launch];
    NS_HANDLER
    task = nil;
    NS_ENDHANDLER
    if(task == nil)
    {
        goto Exit;
    }
    /* Write data to standard input pipe */
    if((fileHandle = [inPipe fileHandleForWriting]))
    {
        NS_DURING
        [fileHandle writeData:inData];
        [fileHandle closeFile];
        NS_HANDLER
        [task terminate];
        [task interrupt];
        task = nil;
        NS_ENDHANDLER
    }
    if(task == nil)
    {
        goto Exit;
    }
    /* Wait for task to complete and read data from standard output and standard error pipes in background */
    if((fileHandle = [outPipe fileHandleForReading]))
    {
        *outData = [NSMutableData data];
        [[NSNotificationCenter defaultCenter] addObserver:*outData selector:@selector(_CommandLineToolFileHandleDataAvailable:) name:NSFileHandleDataAvailableNotification object:fileHandle];
        [fileHandle waitForDataInBackgroundAndNotify];
    }
    if((fileHandle = [errorPipe fileHandleForReading]))
    {
        *errorData = [NSMutableData data];
        [[NSNotificationCenter defaultCenter] addObserver:*errorData selector:@selector(_CommandLineToolFileHandleDataAvailable:) name:NSFileHandleDataAvailableNotification object:fileHandle];
        [fileHandle waitForDataInBackgroundAndNotify];
    }

    //My app is stuck here
    [task waitUntilExit];

    if((fileHandle = [errorPipe fileHandleForReading]))
    {
        [[NSNotificationCenter defaultCenter] removeObserver:*errorData name:NSFileHandleDataAvailableNotification object:fileHandle];
        [(NSMutableData*)*errorData appendData:[fileHandle readDataToEndOfFile]];
    }
    if((fileHandle = [outPipe fileHandleForReading]))
    {
        [[NSNotificationCenter defaultCenter] removeObserver:*outData name:NSFileHandleDataAvailableNotification object:fileHandle];
        [(NSMutableData*)*outData appendData:[fileHandle readDataToEndOfFile]];
    }

Exit:
    [[inPipe fileHandleForReading] closeFile];
    [[inPipe fileHandleForWriting] closeFile];
    [[outPipe fileHandleForReading] closeFile];
    [[outPipe fileHandleForWriting] closeFile];
    [[errorPipe fileHandleForReading] closeFile];
    [[errorPipe fileHandleForWriting] closeFile];

    return (task ? [task terminationStatus] : -1);
}

@end

@implementation NSMutableData (CommandLineTool)

/* Extend the NSMutableData class to add a method called by   NSFileHandleDataAvailableNotification to automatically append the new data */
- (void) _CommandLineToolFileHandleDataAvailable:(NSNotification*)notification
{
    NSFileHandle*           fileHandle = [notification object];

    [self appendData:[fileHandle availableData]];

    [fileHandle waitForDataInBackgroundAndNotify];
}