【发布时间】:2015-03-04 23:53:01
【问题描述】:
我必须计算一个昂贵的价值。计算完这个值后,我想运行一个完成处理程序块:
-(void) performCostlyCalculationWithCompletionHandler:(void (^)(void)complete
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
id result = [self costlyCalculation];
dispatch_async(dispatch_get_main_queue(), ^{
complete(result);
});
});
}
相当标准。
现在,我希望能够重复调用此函数,而无需重新排队 costlyCalculation。如果costlyCalculation 已经在运行,我只想保存完成块并在costlyCalculation 完成后使用相同的result 调用它们。
有没有一种简单的方法可以用 GCD 或 NSOperationQueue 做到这一点?还是我应该将完成块存储在NSArray 中并自己调用它们?如果我这样做,我需要在这个数组周围放置什么样的同步?
更新
我可以接近dispatch_group_notify。基本上,我可以将工作块排入队列并将所有完成处理程序排入队列以在组之后运行:
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queue, ^(){
// Do something that takes a while
id result = [self costlyCalculation];
dispatch_group_async(group, dispatch_get_main_queue(), ^(){
self.result = result;
});
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^(){
complete(result);
});
这可行,但我如何判断costlyCalcuation 是否已经在运行,并且如果我不需要的话,不将工作排入队列?
【问题讨论】:
-
您是否可以将结果保存为 ivar,然后在执行
costlyCalculation之前测试result的存在,或者简单地使用 BOOL 标记函数的开始和结束,然后如果函数正在运行将块添加到数组中,如 q 中所述,并在计算完成后调用所有排队的块。如果你想要一些代码,我之前已经做过这两件事。 -
不想事先检查
result,因为在第一次运行时,多个请求会快速连续出现,这会导致对costlyCalculation的重复调用。也许用 BOOL 标记开始和结束是正确的方法。感谢您的建议。 -
当然,我使用
AVAssetImageGenerator从资产生成缩略图。然后将缩略图绘制成屏幕上不同位置的几个CALayers。AVAssetImageGenerator运行时可见层可能会来来去去。 -
我同意@Rob,但我还要提一下,您可以结合使用 BOOL 方法和 iVar 方法来防止多次调用
costlyCalculation,然后让结果保持不变(这将是如果结果始终相同,则最好每次都解决)。 -
我打电话给
generateCGImagesAsynchronouslyForTimes,生成的图像需要在屏幕上不同位置的几个不同层中重复使用。所以如果在generateCGImagesAsynchronouslyForTimes运行时出现了一个新层,我想在这个新层中重复使用相同的图像而不重新运行图像生成器
标签: ios objective-c grand-central-dispatch nsoperationqueue