如何在GCD中停止DispatchWorkItem? [英] How to stop a DispatchWorkItem in GCD?

查看:260
本文介绍了如何在GCD中停止DispatchWorkItem?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在玩 Grand Central Dispatch ,并发现了一个名为DispatchWorkItem的类.该文档似乎有些不完整,因此我不确定是否正确使用它.我创建了以下代码段,并期望有所不同.我希望该项目在调用cancel后将被取消.但是由于某种原因,迭代仍在继续.有什么想法我做错了吗?该代码对我来说似乎很好.

I am currently playing around with Grand Central Dispatch and discovered a class called DispatchWorkItem. The documentation seems a little incomplete so I am not sure about using it the right way. I created the following snippet and expected something different. I expected that the item will be cancelled after calling cancel on it. But the iteration continues for some reason. Any ideas what I am doing wrong? The code seems fine for me.

@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不会执行抢先取消.因此,要停止已经启动的工作项,您必须自己测试取消.在Swift中, cancel dispatch_block_cancel a href ="https://developer.apple.com/documentation/dispatch/1431050-dispatch_block_create?language=objc" rel ="nofollow noreferrer"> dispatch_block_create .然后,您可以使用 isCancelled 在Swift中(在Objective-C中称为 dispatch_block_testcancel )./p>

GCD does not perform preemptive cancelations. So, to stop a work item that has already started, you have to test for cancelations yourself. In Swift, cancel the DispatchWorkItem. In Objective-C, call dispatch_block_cancel on the block you created with dispatch_block_create. You can then test to see if was canceled or not with isCancelled in Swift (known as dispatch_block_testcancel in Objective-C).

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中:

Or, in 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); }
    });
}

这篇关于如何在GCD中停止DispatchWorkItem?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆