我正在使用信号量等待异步任务完成,但是在以下情况下我不为什么不等待,请告诉我我在哪里做错
NSLog(@"start async task");
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UIImage * image = [UIImage imageNamed:@"image.png"];
[assetLibrary writeImageToSavedPhotosAlbum:image.CGImage
orientation:ALAssetOrientationUp
completionBlock:^(NSURL *assetURL, NSError *error) {
NSLog(@"waiting for block to complete");
}];
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
NSLog(@"finished");
i am getting following output -
start async task ---> finished ----> waiting for block to complete
最佳答案
如blazejmar的注释中所述,您的代码无法正常工作有两个原因:
首先:将文件写入资产库后,您的dispatch_semaphore_signal(sema);
必须在完成调用中
第二个(也是更重要的):您正在阻塞主线程,但是ALAssetsLibrary
需要它来完成映像的写入。
我建议您重构代码并使用其他设计模式,避免阻塞线程。
但是,如果您想要一个“简单,快速”的解决方案,只需将所有代码放到另一个调度中(并按照我的解释移动调度信号)。注意:在此代码中,我添加了一些NSLog调用以打印当前线程,稍后将解释原因
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"Thread id is %i", (int)pthread_self());
ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc]init];
NSLog(@"start async task");
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"Thread id is %i", (int)pthread_self());
UIImage * image = [UIImage imageNamed:@"image.png"];
[assetLibrary writeImageToSavedPhotosAlbum:image.CGImage
orientation:ALAssetOrientationUp
completionBlock:^(NSURL *assetURL, NSError *error) {
NSLog(@"waiting for block to complete");
dispatch_semaphore_signal(sema);
}];
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
NSLog(@"finished");
});
这将工作并打印
2014-07-22 08:49:24.488 Asset[66697:1139580] start async task
2014-07-22 08:49:27.709 Asset[66697:1139582] waiting for block to complete
2014-07-22 08:49:27.710 Asset[66697:1139580] finished
关于
ALAssetsLibrary
对主线程的使用:我在文档中找不到它,但是您可以轻松地找到执行以下操作的系统调用使用了哪个线程(也许有人有一个更简单的方法):
如上所述,将NSLog调用放入您的代码中。
在
objc_msgSend
上使用以下表达式创建一个符号断点:expr -- (void)printf("[%s, %s] - Thread: %i\n",(char *) object_getClassName(*(long*)($esp+4)), (char *) *(long *)($esp+8), (int) pthread_self())
。这将打印所有带有其调用线程的方法调用在
[assetLibrary writeImageToSavedPhotosAlbum]
之后立即启用断点就我而言:
2014-07-22 08:42:59.892 Asset [66411:1135166]线程ID为84767144 2014-07-22 08:42:59.893 Asset [66411:1135251]线程ID为-1341575168 2014-07-22 08:42:59.893 Asset [66411:1135252]线程ID为-1341042688
[assetLibrary writeImageToSavedPhotosAlbum]
之后立即开始记录[nil,CGImage]-线程:-1341042688
[OS_dispatch_semaphore,保留]-线程:-1341042688
[ALAssetsLibrary,writeImageToSavedPhotosAlbum:orientation:completionBlock:]-线程:-1341042688
[CFPrefsDirectSource,createRequestNewContentMessageForDaemon:]-线程:84767144
因此,如果您阻塞主线程,您的代码将在该调用时阻塞。
关于ios - ios-信号量不等待ALAssetsLibrary writeImageToSavedPhotosAlbum方法完成,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24864574/