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 目标C等待异步任务处理完成_Objective C_Multithreading - Fatal编程技术网

Objective c 目标C等待异步任务处理完成

Objective c 目标C等待异步任务处理完成,objective-c,multithreading,Objective C,Multithreading,在我的代码中,我运行的是一个本地服务器(CocoaHTTPServer)。当服务器收到请求时,它会创建一个线程并将控制权传递给某个方法((NSObject*)httpResponseForMethod:(NSString*)方法URI:(NSString*)path,这里可能不相关) 我需要阅读本地资产列表并返回结果。API调用([assetsLibrary enumerateGroupsWithTypes:AlasSetGroupAll usingBlock:^(AlasSetGroup*gr

在我的代码中,我运行的是一个本地服务器(CocoaHTTPServer)。当服务器收到请求时,它会创建一个线程并将控制权传递给某个方法(
(NSObject*)httpResponseForMethod:(NSString*)方法URI:(NSString*)path
,这里可能不相关)

我需要阅读本地资产列表并返回结果。API调用(
[assetsLibrary enumerateGroupsWithTypes:AlasSetGroupAll usingBlock:^(AlasSetGroup*group,BOOL*stop).
)是异步的

由于HTTPResponse需要等待API调用完成,因此我创建了一个名为
\u isProcessing
的标志,我在进行API调用之前设置了该标志。调用完成后,我将取消设置该标志并返回HTTP请求。要等待的代码如下所示:

// the API call is non-blocking. hence, wait in a loop until the command has finished
samCommand->isProcessing = YES;
while (samCommand->isProcessing) {
    usleep(100*1000);
}
API调用在完成其任务时调用委托方法,如下所示:

// to be called at the end of an asynch operation (eg: reading local asset list)
- (void) commandDidFinish {
    // flag to open the lock
    isProcessing = NO;
}
    @implementation SAMCommand {
    NSData* resultData;
    dispatch_semaphore_t semaphore; // a lock to establish whether the command has been processed
}

// construct the object, ensuring that the "command" field is present in the jsonString
+(NSData*) createAndExecuteCommandWithJSONParamsAs:(NSString *)jsonString {

    SAMCommand* samCommand = [[SAMCommand alloc] init];

    samCommand.commandParams = [jsonString dictionaryFromJSON];

    if(COMPONENT==nil || COMMAND==nil){
        DDLogError(@"command not found in %@",jsonString);
        return nil;
    }

    samCommand->semaphore = dispatch_semaphore_create(0);
    DDLogInfo(@"created semaphore %p->%p",samCommand,samCommand->semaphore);

    // to execute a command contained in the jsonString, we use reflection. 
    DDLogInfo(@"calling execute with %p",samCommand);
    [NSClassFromString(COMPONENT) performSelectorOnMainThread:NSSelectorFromString([NSString stringWithFormat:@"%@_%@_%@:",COMMAND,MEDIA_SOURCE,MEDIA_TYPE]) withObject:samCommand waitUntilDone:NO];

    // the above calls are non-blocking. hence, wait in a loop until the command has finished
    DDLogInfo(@"starting wait loop %p->%p",samCommand,samCommand->semaphore);
    dispatch_semaphore_wait(samCommand->semaphore, DISPATCH_TIME_FOREVER);
    DDLogInfo(@"ending wait loop %p->%p",samCommand,samCommand->semaphore);
    DDLogInfo(@"");

    // return the data
    return samCommand->resultData;

}

// to be called at the end of an asynch operation (eg: reading local asset list)
- (void) commandDidFinish {

    // flag to release the lock
    DDLogInfo(@"releasing semaphore %p->%p",self,semaphore);
    dispatch_semaphore_signal(semaphore);
    semaphore = nil;

}

@end
这是可行的,但可能需要性能增强。我如何在这里使用任何东西(运行循环等)来提高性能


使用dispatch_信号量编辑以下weichsel解决方案 按照weichsel的解决方案,我创建了一个信号量。我的代码顺序是:

  • CocoaHTTPServer接收一个请求,因此创建一个新线程
  • 它调用命令类的静态方法来执行请求
  • Command类创建一个新的Command对象来调用另一个类(使用反射),该类调用alassetapi并将Command对象传递给它
  • 返回时,ALAsset API调用调用的委托方法 命令类
  • 因此,我在适当的位置嵌入了信号量。但是,信号量的等待循环有时不会结束。正常的输出应该是:

    2014-02-07 11:27:23:214 MM2Beta[7306:1103] HTTPServer: Started HTTP server on port 1978
    2014-02-07 11:27:23:887 MM2Beta[7306:6303] created semaphore 0x1f890670->0x1f8950a0
    2014-02-07 11:27:23:887 MM2Beta[7306:6303] calling execute with 0x1f890670
    2014-02-07 11:27:23:887 MM2Beta[7306:6303] starting wait loop 0x1f890670->0x1f8950a0
    2014-02-07 11:27:23:887 MM2Beta[7306:907] calling getAssetsList with delegate 0x1f890670
    2014-02-07 11:27:24:108 MM2Beta[7306:907] calling delegate [0x1f890670 commandDidFinish]
    2014-02-07 11:27:24:108 MM2Beta[7306:907] releasing semaphore 0x1f890670->0x1f8950a0
    2014-02-07 11:27:24:109 MM2Beta[7306:6303] ending wait loop 0x1f890670->0x0
    
    在每几次运行中,最后一步(
    结束等待循环0x1f890670->0x0
    不会发生)。因此,等待循环永远不会结束。有时代码也会在同一点崩溃。这里有什么错误的线索吗

    我的代码如下:

    // to be called at the end of an asynch operation (eg: reading local asset list)
    - (void) commandDidFinish {
        // flag to open the lock
        isProcessing = NO;
    }
    
        @implementation SAMCommand {
        NSData* resultData;
        dispatch_semaphore_t semaphore; // a lock to establish whether the command has been processed
    }
    
    // construct the object, ensuring that the "command" field is present in the jsonString
    +(NSData*) createAndExecuteCommandWithJSONParamsAs:(NSString *)jsonString {
    
        SAMCommand* samCommand = [[SAMCommand alloc] init];
    
        samCommand.commandParams = [jsonString dictionaryFromJSON];
    
        if(COMPONENT==nil || COMMAND==nil){
            DDLogError(@"command not found in %@",jsonString);
            return nil;
        }
    
        samCommand->semaphore = dispatch_semaphore_create(0);
        DDLogInfo(@"created semaphore %p->%p",samCommand,samCommand->semaphore);
    
        // to execute a command contained in the jsonString, we use reflection. 
        DDLogInfo(@"calling execute with %p",samCommand);
        [NSClassFromString(COMPONENT) performSelectorOnMainThread:NSSelectorFromString([NSString stringWithFormat:@"%@_%@_%@:",COMMAND,MEDIA_SOURCE,MEDIA_TYPE]) withObject:samCommand waitUntilDone:NO];
    
        // the above calls are non-blocking. hence, wait in a loop until the command has finished
        DDLogInfo(@"starting wait loop %p->%p",samCommand,samCommand->semaphore);
        dispatch_semaphore_wait(samCommand->semaphore, DISPATCH_TIME_FOREVER);
        DDLogInfo(@"ending wait loop %p->%p",samCommand,samCommand->semaphore);
        DDLogInfo(@"");
    
        // return the data
        return samCommand->resultData;
    
    }
    
    // to be called at the end of an asynch operation (eg: reading local asset list)
    - (void) commandDidFinish {
    
        // flag to release the lock
        DDLogInfo(@"releasing semaphore %p->%p",self,semaphore);
        dispatch_semaphore_signal(semaphore);
        semaphore = nil;
    
    }
    
    @end
    
    我让它工作了:)


    最后,似乎稳定工作的是创建信号量,并将其传递给ALAsset asynch API调用,并在调用结束时释放它。之前,我在调用创建信号量的类的委托方法,信号量对象以某种方式得到释放。不确定那里到底发生了什么。

    NSRunLoop有一个名为RunUntelDate的方法:该方法应该适用于您在不久的将来使用的日期,例如提前1秒左右。这样,您可以用以下方法替换while循环中的睡眠调用:

    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeintervalSinveNow:1]
    

    您可以使用信号量阻止当前队列的执行,直到另一个队列返回。
    基本模式是:

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    [assetsLibrary enumerateAssetsUsingBlock^(ALAsset *result, NSUInteger index, BOOL *stop):^{
        ...
        dispatch_semaphore_signal(semaphore);
    }];
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    dispatch_release(semaphore);
    
    您可以在Apple的MTAudioProcessingTap Xcode项目中找到此方法的完整示例:

    相关的行从MYViewController开始。m:86

    非常感谢。那么原则上,usleep()和而你的方法呢?他们不是都在创建一个等待循环,轮询给定的时间量……在这种情况下为100毫秒吗?那么性能增强从何而来?睡眠确实会阻止运行循环的处理。我的方法不会这样做。在GUI应用程序中,你会在调用睡眠时看到旋转的等待光标。非常感谢。我使用请查看我的编辑,看看你是否能发现错误。