这是使用 GCD 编程时一个半常见的问题。
简而言之,GCD 没有用于队列的取消 API。理由:
- 内存管理将变得更加复杂,因为给定的块可能负责 free() 给定的内存分配。通过始终运行该块,GCD 确保内存管理保持轻松。
- 实际上不可能停止running阻止而不破坏状态。
- 大多数需要取消逻辑的代码已经在私有数据结构中跟踪该状态。
考虑到所有这些情况,编写如下代码会更加高效和强大:
dispatch_async(my_obj->queue, ^{
bool done = false;
// do_full_update() takes too long, therefore:
while ( !my_obj->cancelled && !done ) {
done = do_partial_update(my_obj);
}
});
哦,要知道队列是否已完成运行所有排队的块,您的代码可以简单地使用以下命令执行一个空块:同步 API:
dispatch_sync(my_obj->queue, ^{});
正如评论中提到的,了解工作何时完成的更好方法是使用调度组。将所有块分派到该组,然后您可以向该组添加完成处理程序。一旦工作完成,完成块就会运行。
dispatch_group_t myGroup = dispatch_group_create();
dispatch_group_async(myGroup, my_obj->queue, ^{
bool done = false;
while ( !my_obj->cancelled && !done ) {
done = do_partial_update(my_obj);
}
});
dispatch_group_notify(myGroup, my_obj->queue, ^{
NSLog(@"Work is done!");
dispatch_release(myGroup);
});
一旦所有块完成,该组将为空并触发通知块。从那里,您可以更新 UI 等。
祝好运并玩得开心点!