当不再需要时,在dispatch_async中取消操作

时间:2014-09-17 15:32:08

标签: ios objective-c grand-central-dispatch

我有UIViewControllerviewDidLoad

中执行以下操作
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    items = [[DataFetcher sharedInstance] getItems handler:^(NSArray *currentItems){
        if (currentItems.count % 30 == 0) { //don't wait for all the items to be ready show by chunks of 30
            items = currentItems;
            [tableView reloadData];
        }
        items = currentItems;
    }];//Pretty complex call that takes some time to finish there is WebService calls, data parsing, storing some results ...
    dispatch_async(dispatch_get_main_queue(), ^{
        [tableView reloadData];
    });
});

我需要做的是在弹出此viewController时停止getItems。它毫无意义,需要CPU时间和精力(在某些情况下,此呼叫可能需要一分钟)。

我假设我应该在viewWillDisappear中这样做,但究竟是怎么做的?

2 个答案:

答案 0 :(得分:1)

您可以使用NSBlockOperation。定期检查是否已取消,如果已经取消,则停止工作:

- (void)getItemsWithHandler:(void (^)(NSArray *currentItems))handler {
    self.operation = [NSBlockOperation blockOperationWithBlock:^{
        if (self.operation.isCancelled) {
            return;
        }

        // Do something expensive

        if (self.operation.isCancelled) {
            return;
        }

        // Do something else expensive

        for (int i = 0; i < 10000; i++) {
            if (self.operation.isCancelled) {
                return;
            }

            // Do expensive things in a loop
        }
    }];
}

- (void) cancelGetItemsRequest {
    [self.operation cancel];
    self.operation = nil;
}

或者,您可以在NSBlockOperation中添加一堆NSOperationQueue个。您可以设置工作的依赖关系,并根据需要立即取消整个队列。

答案 1 :(得分:0)

在NSOperation和NSOperationQueue中很好地支持取消异步操作,但它要复杂得多。在任何情况下,您的异步代码都必须不时检查它是否被取消或应该继续。

最好的办法是在某个地方“取消”某个属性,当你不想再做任何工作时设置,并且每当你尝试做更多的工作时,你都会检查该属性。