【发布时间】:2020-11-05 13:32:21
【问题描述】:
我有许多 NSBlockOperations 链,具有依赖关系。如果链中早期的一项操作失败 - 我希望其他操作不运行。根据文档,这应该很容易从外部完成 - 如果我取消一个操作,所有相关操作都应该自动取消。
但是 - 如果只有我的操作的执行块“知道”它在执行时失败 - 它可以cancel 自己的工作吗?
我尝试了以下方法:
NSBlockOperation *op = [[NSBlockOperation alloc] init];
__weak NSBlockOperation *weakOpRef = op;
[takeScreenShot addExecutionBlock:^{
LOGInfo(@"Say Cheese...");
if (some_condition == NO) { // for some reason we can't take a photo
[weakOpRef cancel];
LOGError(@"Photo failed");
}
else {
// take photo, process it, etc.
LOGInfo(@"Photo taken");
}
}];
但是,当我运行它时,即使 op 被取消,其他依赖于 op 的操作也会执行。因为它们是依赖的——在op 完成之前它们肯定不会开始,并且我验证(在调试器和使用日志中)op 的isCancelled 状态在块返回之前是YES。队列仍然像op 成功完成一样执行它们。
然后我进一步挑战文档,如下所示:
NSOperationQueue *myQueue = [[NSOperationQueue alloc] init];
NSBlockOperation *op = [[NSBlockOperation alloc] init];
__weak NSBlockOperation *weakOpRef = takeScreenShot;
[takeScreenShot addExecutionBlock:^{
NSLog(@"Say Cheese...");
if (weakOpRef.isCancelled) { // Fail every once in a while...
NSLog(@"Photo failed");
}
else {
[NSThread sleepForTimeInterval:0.3f];
NSLog(@"Photo taken");
}
}];
NSOperation *processPhoto = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Processing Photo...");
[NSThread sleepForTimeInterval:0.1f]; // Process
NSLog(@"Processing Finished.");
}];
// setup dependencies for the operations.
[processPhoto addDependency: op];
[op cancel]; // cancelled even before dispatching!!!
[myQueue addOperation: op];
[myQueue addOperation: processPhoto];
NSLog(@">>> Operations Dispatched, Wait for processing");
[eventQueue waitUntilAllOperationsAreFinished];
NSLog(@">>> Work Finished");
但是惊恐地在日志中看到以下输出:
2020-11-05 16:18:03.803341 >>> Operations Dispatched, Wait for processing
2020-11-05 16:18:03.803427 Processing Photo...
2020-11-05 16:18:03.813557 Processing Finished.
2020-11-05 16:18:03.813638+0200 TesterApp[6887:111445] >>> Work Finished
注意:取消的操作从未运行 - 但依赖的 processPhoto 已执行,尽管它依赖于 op。
有什么想法吗?
【问题讨论】:
-
听起来很熟悉,比如stackoverflow.com/questions/64671948/… 可能吗? PS在那里我给出了一个如何做到这一点的样本。在那个答案中,我们进行了很多讨论,最终我编辑了我的答案并对其进行了相当多的更改,但是我认为我的答案的第一部分中涵盖了您想要做什么以及示例实现。
-
PPS : 你有正确的想法,但需要同步你的条件并使用你自己的逻辑。
-
我仔细阅读了参考资料,我的问题非常不同。首先,我的代码中没有任何异步,除了由并发 NSOperationQueue 运行的实际 NSOperations。另外 - 我不混合 GCD 和 NSOperation API。下一步 - 我不是在问如何实现实际取消 - 而是关于取消操作的影响 - (据我了解)它不像宣传的那样起作用(或者也许有人可以告诉我它是)
标签: objective-c macos objective-c-blocks nsoperationqueue nsoperation