我有一个方法,在我的代码中有时会被调用。下面是一个非常基本的例子,因为该代码处理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");
});
}
我认为每次调用此方法,我都会得到以下输出... “正在处理图像” “完成处理图像” “正在处理图像” “完成处理图像” 等等...
但我总是得到
“正在处理图像” “正在处理图像” “完成处理图像” “完成处理图像” 等等...
我认为串行队列会等待第一个块完成后再开始。在我看来,它似乎是在启动方法,然后再次调用并在第一个调用完成之前启动,创建通常不会被处理的图像的副本,因为如果它真正按顺序执行,该方法将知道它们已经被处理。也许我的串行队列的理解还不够深刻。有任何建议吗?谢谢。
编辑:更多上下文如下,这是块中正在发生的事情...这可能会导致问题吗?
@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: 我认为正在发生的事情,请在评论中表示同意/不同意...
显然,我的主要问题是,当并发执行此代码块时,会创建重复条目(导入相同的照片),而如果按顺序运行,则不会发生这种情况。处理照片时会将“脏”标记应用于它,以确保下一次调用该方法时跳过此图像,但是这并没有发生,有些图像被处理了两次。这是否由于我正在使用enumerategroupswithtypes:在serialQueue内枚举第二个队列中的对象引起的呢?
- 调用processImages
- 枚举对象
- 立即从enumerateObjects返回,因为它本身是异步的
- 结束对processImages的调用
虽然枚举组可能仍在运行,但由于队列在枚举组完成工作之前已经到达块的末尾,因此processImages实际上并未完成。我认为这似乎是一种可能性?
dispatch_queue_create
。也许在那里放一个NSLog
语句。你的期望是正确的(它应该是严格串行的),但还有其他简单的事情发生了。 - Robdispatch_async
调用处设置一个断点,并验证每次调用processImages
时serialQueue
是相同的对象。听起来你的队列正在被重新创建。 - Tom Redman