到目前为止,我已经阅读了GCD的文档,但似乎错过了dispatch_cancel()我想用它来取消所有调度的块调用。 有没有办法实现dispatch_cancel()?
答案 0 :(得分:10)
正如@HampusNilsson所提到的,你不能合理地取消任何在非垃圾收集环境(例如这个)中的飞行中操作,因为它本身会泄漏资源并使进程处于不确定状态。 NSOperationQueue
具有取消API,并且该API可用于实现取消正在进行的操作,前提是操作本身正在协作检查该标志,然后提前清理并返回。这不是真正的,难以中止。
至于取消已入队但尚未开始的工作项,是的,NSOperationQueue
处理此问题,但这需要额外的费用,NSOperationQueue
是更高级别的抽象。 GCD的性能很大程度上取决于无锁队列的内部使用。无锁队列比基于锁的实现更快,但是为了达到这个速度,需要进行一些权衡。例如,我认为以无锁方式任意改变队列以删除已取消的操作会更加困难。我怀疑将公开的队列操作限制为“仅排队”,并使工作项本身不可变(块和函数ptrs),为许多优化提供了大门,这些优化允许GCD具有如此小的开销并且表现良好。 / p>
FWIW,在通常情况下,在现有的GCD API之上实现取消操作非常简单,因此任何需要此功能的人都可以很容易地自己完成(并且可能以更适合的方式)他们的具体需求比普通的API更好。考虑以下函数 - 它将队列上的一个块排队并返回一个块,您可以稍后调用它来取消排队操作:
dispatch_block_t dispatch_cancelable_async(dispatch_queue_t q, dispatch_block_t b)
{
__block uintptr_t isCancelled = 0;
dispatch_async(q, ^{
if (!isCancelled) b();
});
return [[^{ isCancelled = 1; } copy] autorelease];
}
对于每种情况,这都不是正确的取消方法,但它是一个不错的第一近似值。
“使用最高级别的抽象来完成工作。”如果您想要取消,并且NSOperationQueue
和GCD之间的开销差异不是一个重要因素,您应该只使用NSOperationQueue
。有些人甚至认为在Objective-C中工作时使用NSOperationQueue
是更惯用的选择。除此之外,如图所示,对GCD之上的常见情况实施非中止取消是相当微不足道的。
基于这一切,我怀疑在API的取消方面建立在性能和复杂性方面并不值得权衡。
答案 1 :(得分:1)
从iOS 8及更高版本,你可以用
取消块执行
dispatch_block_cancel
SET @term = "someterm"
SELECT DISTINCT
posts.id,
posts.post_author,
posts.post_title,
posts.post_date,
LEFT(posts.post_content,300) post_content,
wpmeta.meta_value thumbnail
FROM wp_posts posts
INNER JOIN wp_postmeta wpm ON posts.id = wpm.post_id
INNER JOIN wp_postmeta wpmeta ON wpm.meta_value = wpmeta.post_id
LEFT JOIN wp_term_relationships rel ON rel.object_id = posts.ID
LEFT JOIN wp_term_taxonomy tax ON tax.term_taxonomy_id = rel.term_taxonomy_id
LEFT JOIN wp_terms t ON t.term_id = tax.term_id
WHERE
post_status = 'publish'
AND posts.post_type = 'post'
AND wpm.meta_key = '_thumbnail_id'
AND wpmeta.meta_key = '_wp_attached_file'
AND 1 =
CASE
WHEN @term IS NULL THEN 1
WHEN @term IS NOT NULL AND t.term_id = @term THEN 1
ELSE 0
END
ORDER BY post_date DESC
答案 2 :(得分:0)
GCD没有实现取消API,因为它不安全(它可能在运行中中止线程)。如果你想取消任务,你需要自己动手,通过实现一个“已取消”的布尔值,并在它们开始时和之后定期检查你的任务。