Objective c 目标C等待异步任务处理完成
在我的代码中,我运行的是一个本地服务器(CocoaHTTPServer)。当服务器收到请求时,它会创建一个线程并将控制权传递给某个方法(Objective c 目标C等待异步任务处理完成,objective-c,multithreading,Objective C,Multithreading,在我的代码中,我运行的是一个本地服务器(CocoaHTTPServer)。当服务器收到请求时,它会创建一个线程并将控制权传递给某个方法((NSObject*)httpResponseForMethod:(NSString*)方法URI:(NSString*)path,这里可能不相关) 我需要阅读本地资产列表并返回结果。API调用([assetsLibrary enumerateGroupsWithTypes:AlasSetGroupAll usingBlock:^(AlasSetGroup*gr
(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的解决方案,我创建了一个信号量。我的代码顺序是:
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应用程序中,你会在调用睡眠时看到旋转的等待光标。非常感谢。我使用请查看我的编辑,看看你是否能发现错误。