【发布时间】:2024-01-21 20:10:01
【问题描述】:
我正在创建一个这样的串行后台队列:
@property (nonatomic, strong) dispatch_queue_t assetCreationQueue;
// in init...
_assetCreationQueue = dispatch_queue_create("com.mycompany.assetCreationQueue", DISPATCH_QUEUE_SERIAL);
然后我像这样在后台枚举 ALAsset 对象:
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop){
if (asset){
dispatch_async(weakSelf.assetCreationQueue, ^{
ALAssetRepresentation *assetRepresentation = [asset defaultRepresentation];
NSURL *url = [assetRepresentation url];
if (url) {
AVURLAsset *avAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
// This NSLog fires! avAsset exists.
NSLog(@"AVURLAsset %@", avAsset);
dispatch_async(dispatch_get_main_queue(), ^{
// This NSLog NEVER fires.
// Also tried dispatch_sync.
NSLog(@"add to assets array on main queue");
[weakSelf.assets insertObject:avAsset atIndex:0];
});
}
});
}
}];
assets数组属性定义为:
@property (nonatomic, strong) NSMutableArray *assets;
当我尝试dispatch_sync(dispatch_get_main_queue(), ^{ 时,我在控制台中只得到一个NSLog(@"AVURLAsset %@", avAsset);,这表明dispatch_sync 正在导致死锁。
但是我怎样才能找出原因呢?我看不出在哪里。 assetsCreationQueue 是一个后台队列,我只能在主队列上对数组进行操作。
编辑: 这是一个更加简化的测试,它也失败了:
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop){
if (asset){
dispatch_async(weakSelf.assetCreationQueue, ^{
if ([NSThread isMainThread]) {
NSLog(@"already main thread"); // gets called often!!
} else {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"dispatch async on main queue"); // never gets called!!
});
}
});
}
}];
所以我不明白的是:为什么我已经在主线程上,即使我调用了dispatch_async(weakSelf.assetCreationQueue。它只能导致邪恶的结论:我创建的队列不是后台队列:
_assetCreationQueue = dispatch_queue_create("com.mycompany.assetCreationQueue", DISPATCH_QUEUE_SERIAL);
为什么?
【问题讨论】:
-
您能否再次检查更新后的代码是否是您实际测试的代码?它缺少一个括号。
-
@RobNapier 已修复。当我尝试在 SO 代码编辑器中对其进行格式化时,它被意外删除了。这是我正在测试的代码。
-
看起来你的后台队列和主队列是一回事。你能注销
weakSelf.assetCreationQueue和NSLog(@"%p", queue);返回的内容来确认/反驳吗? -
不幸的是,我在这段代码上搞砸了很多,因为帖子现在完全不同了。但似乎 AVAssetLibrary -enumerateAssetsUsingBlock 方法正在使用 dispatch_sync(dispatch_get_main_queue(),...) 如果我尝试在主队列上分派块,则会导致死锁。
标签: iphone ios objective-c concurrency grand-central-dispatch