我目前正在玩 Grand Central Dispatch ,发现了一个名为的课程DispatchWorkItem。该文档似乎有些不完整,所以我不确定是否正确使用它。我创建了以下代码段,并期望有所不同。我预计该项目将在调用后被取消cancel。但是由于某种原因,迭代仍在继续。有什么想法我做错了吗?该代码对我来说似乎很好。
DispatchWorkItem
cancel
@IBAction func testDispatchItems() { let queue = DispatchQueue.global(attributes:.qosUserInitiated) let item = DispatchWorkItem { [weak self] in for i in 0...10000000 { print(i) self?.heavyWork() } } queue.async(execute: item) queue.after(walltime: .now() + 2) { item.cancel() } }
GCD不会执行抢先取消。因此,要停止已经开始的工作项,您必须自己测试取消。在斯威夫特cancel的DispatchWorkItem。在Objective- C中,调用dispatch_block_cancel用创建的块dispatch_block_create。然后,您可以测试isCancelled在Swift中是否被取消(dispatch_block_testcancel在Objective- C中称为)。
dispatch_block_cancel
dispatch_block_create
isCancelled
dispatch_block_testcancel
func testDispatchItems() { let queue = DispatchQueue.global() var item: DispatchWorkItem? // create work item item = DispatchWorkItem { [weak self] in for i in 0 ... 10_000_000 { if item?.isCancelled ?? true { break } print(i) self?.heavyWork() } item = nil // resolve strong reference cycle of the `DispatchWorkItem` } // start it queue.async(execute: item!) // after five seconds, stop it if it hasn't already queue.asyncAfter(deadline: .now() + 5) { item?.cancel() item = nil } }
或者,在Objective-C中:
- (void)testDispatchItem { dispatch_queue_t queue = dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0); static dispatch_block_t block = nil; // either static or property __weak typeof(self) weakSelf = self; block = dispatch_block_create(0, ^{ for (long i = 0; i < 10000000; i++) { if (dispatch_block_testcancel(block)) { break; } NSLog(@"%ld", i); [weakSelf heavyWork]; } block = nil; }); // start it dispatch_async(queue, block); // after five seconds, stop it if it hasn't already dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ if (block) { dispatch_block_cancel(block); } }); }