gpt4 book ai didi

ios - GCD串行队列好像没有串行执行

转载 作者:可可西里 更新时间:2023-11-01 03:57:20 25 4
gpt4 key购买 nike

我有一个方法,有时可以在我的代码中调用它。下面是一个非常基本的示例,因为代码会处理来自 iPhone 照片库的图像和文件,并在使用该方法完成后将它们标记为已处理。

@property (nonatomic, assign) dispatch_queue_t serialQueue;

....

-(void)processImages
{
dispatch_async(self.serialQueue, ^{
//block to process images
NSLog(@"In processImages");

....

NSLog(@"Done with processImages");
});
}

我认为每次调用此方法时我都会得到以下输出...“处理中图片”“完成 processImages”“处理中图片”“完成 processImages”等等……

但我总是得到

“处理中的图片”“处理中图片”“完成 processImages”“完成 processImages”等等……

我认为串行队列会等到第一个 block 完成,然后开始。对我来说,它似乎正在启动该方法,然后它被再次调用并在第一次调用甚至完成之前启动,创建通常不会被处理的图像副本,因为如果它真的串行执行,该方法会知道它们已经被处理了。也许我对串行队列的理解并不具体。任何输入?谢谢你。

编辑:下面的更多上下文,这是 block 中发生的事情......这会导致问题吗???

@property (nonatomic, assign) dispatch_queue_t serialQueue;

....

-(void)processImages
{
dispatch_async(self.serialQueue, ^{
//library is a reference to ALAssetsLibrary object

[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop)
{
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop)
{
....
//Process the photos here
}];
failureBlock:^(NSError *error) { NSLog(@"Error loading images from library");
}];

});
}

-(id)init
{
self = [super init];
if(self)
{
_serialQueue = dispatch_queue_create("com.image.queue",NULL);
}
return self;
}

此对象仅创建一次,据我所知,根据我的代码永远无法再次创建...我将运行测试以确保。

更新 2:我认为正在发生的事情,如果您同意/不同意,请对此发表评论....

显然,我的主要问题是,这 block 代码似乎是同时执行的,创建了重复的条目(两次导入同一张照片),而如果它是串行运行的,通常不会这样做。当一张照片被处理时,一个“脏”位被应用到它确保下次调用该方法时它会跳过这个图像,但这并没有发生,一些图像被处理了两次。这可能是因为我在该 serialQueue 中使用 enumerategroupswithtypes: 枚举第二个队列中的对象吗?

  1. 调用processImages
  2. 枚举对象
  3. 立即从 enumerateObjects 返回,因为它本身是异步的
  4. 结束调用 processImages

processImages 并没有真正完成,因为 enumerategroups 可能仍在运行,但队列可能认为它已完成,因为它在 enumerategroups 完成工作之前到达 block 的末尾。这对我来说似乎是一种可能性?

最佳答案

串行队列绝对会串行执行。但是,不能保证它们在同一线程上执行。

假设您使用相同的串行队列,问题是当从不同线程近距离同时调用时,不能保证 NSLog 以正确的顺序输出结果。

这是一个例子:

  1. SQ 在线程 X 上运行,发送“In processImages”
  2. 日志打印“处理中”
  3. 线程 X 上的 SQ,发送“处理图像完成”
  4. SQ 在线程 Y 上运行,发送“In processImages”
  5. 日志打印“essImages\n”

5.之后,NSLog不一定知道要打印哪个,3.还是4.

如果你绝对需要按时间排序的日志记录,你需要一个专门的队列来进行日志记录。实际上,我只使用主队列没有遇到任何问题:

dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"whatever");
});

如果所有 NSlog 调用都在同一个队列中,则不会出现此问题。

关于ios - GCD串行队列好像没有串行执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15618579/

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