gpt4 book ai didi

ios - 信号量不等待 ALAssetsLibrary writeImageToSavedPhotosAlbum 方法完成

转载 作者:行者123 更新时间:2023-11-28 22:02:06 29 4
gpt4 key购买 nike

我正在使用信号量等待异步任务完成,但我不知道为什么在下面的情况下它不等待,请告诉我我哪里做错了

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); 必须在完成调用中,在文件被写入 Assets 库之后

其次(也是更重要的一点):您阻塞了主线程,但是 ALAssetsLibrary 需要它来完成图像的写入。

我建议您重构代码并使用不同的设计模式,避免阻塞线程。但是,如果您想要一个“简单而快速”的解决方案,只需在所有代码周围放置另一个分派(dispatch)(并按照我的解释移动分派(dispatch)信号)。注意:在这段代码中我添加了一些 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 Assets [66411:1135166] 线程 ID 为 84767144 <-- 主线程2014-07-22 08:42:59.893 Assets [66411:1135251] 线程 ID 为 -1341575168 <-- 后台线程 12014-07-22 08:42:59.893 Assets [66411:1135252] 线程 ID 为 -1341042688 <-- 后台线程 2

日志在 [assetLibrary writeImageToSavedPhotosAlbum] 之后立即开始

[无,CGImage] - 主题:-1341042688[OS_dispatch_semaphore,保留] - 线程:-1341042688[ALAssetsLibrary, writeImageToSavedPhotosAlbum:orientation:completionBlock:] - 线程:-1341042688[CFPrefsDirectSource, createRequestNewContentMessageForDaemon:] - 线程:84767144 <--- BINGO,第一条消息到主线程

因此,如果您阻塞主线程,您的代码将阻塞该调用。

关于ios - 信号量不等待 ALAssetsLibrary writeImageToSavedPhotosAlbum 方法完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24864574/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com