简体   繁体   English

并非每次都调用并发NSOperation的完成块

[英]Completion Block of concurrent NSOperation not being called everytime

I would like to run a concurrent NSOperation. 我想运行一个并发的NSOperation。 For this reason, I have extended the NSOperation class and overridden the start and finish methods. 因此,我扩展了NSOperation类并覆盖了start和finish方法。 It looks something like this: 看起来像这样:

#import "AVFrameConversionOP.h"


@implementation AVFrameConversionOP //extends NSOperation

- (void)start
{

    [self willChangeValueForKey:@"isFinished"];
    _isFinished = NO;
    [self didChangeValueForKey:@"isFinished"];

    // Begin
    [self willChangeValueForKey:@"isExecuting"];
    _isExecuting = YES;
    [self didChangeValueForKey:@"isExecuting"];

    if (_isCancelled == YES) {
        NSLog(@"** OPERATION CANCELED **");
        [self willChangeValueForKey:@"isFinished"];
        _isFinished = YES;
        [self didChangeValueForKey:@"isFinished"];
        return;
    } 

    [self performTask];
    [self finish];

}

- (void)finish
{

    [self willChangeValueForKey:@"isExecuting"];
    [self willChangeValueForKey:@"isFinished"];

    _isExecuting = NO;
    _isFinished = YES;

    [self didChangeValueForKey:@"isExecuting"];
    [self didChangeValueForKey:@"isFinished"];

    NSLog(@"operationfinished, _isFinished is %d", _isFinished);

    if (_isCancelled == YES)
    {
        NSLog(@"** OPERATION CANCELED **");
    }
}

- (void)performTask
{
    //The task is performed here
    sleep(0.1); //This is just for demonstration purposes
}
@end

I have defined the completion block for this NSOperation in the main view controller in the viewDidLoad method: 我已经在viewDidLoad方法的主视图控制器中为此NSOperation定义了完成块:

- (void)viewDidLoad {

NSLog(@"viewDidLoad!");
[super viewDidLoad];

static int counter = 0;


_frameConvOP = [[AVFrameConversionOP alloc] init]; //Initializing the modified NSOperation class
__weak typeof(self) weakSelf = self;
_frameConvOP.completionBlock = ^ {
    counter++;
    //NSLogs don't seem to work here
    /*if(counter>1){
         exit(-1); //Never happens because counter only ever becomes =1
    }*/

};
[[VideoPreviewer instance] setNSOperation:_frameConvOP]; //This is where I send the NSOperation object to the class where I'm using it

}

I'm starting the NSOperation by doing [frameConvOP start] inside of a loop. 我通过在循环内执行[frameConvOP start] It is called continuously every time a frame is decoded, so that is to say it is called very often. 每次解码帧时都会连续调用它,也就是说,它经常被调用。 I can see that the finish and start methods of the NSOperation are being called frequently through the logs. 我可以看到NSOperation的finishstart方法经常通过日志被调用。 And the functions inside these methods are also being correctly called. 这些方法中的函数也被正确调用。 However, the NSLogs inside the completion blocked aren't logged. 但是,不会记录完成中的NSLogs。 I put an exit(-1) inside the completion block and the app crashed, but the NSLogs never show up. 我在完成块中放入了一个exit(-1),应用程序崩溃了,但NSLogs却从未显示出来。 So I put a static counter in there and it only increments to 1. So the completion block is only being called once. 因此,我在其中放置了一个静态计数器,它仅增加到1。因此,完成块仅被调用一次。

Can anyone explain why the completion block is being called only once? 谁能解释为什么仅一次调用完成块? Is it because of the way I'm (incorrectly) handling the KVO for _isFinished and _isExecuting ? 是因为我(错误地)处理_isFinished_isExecuting的KVO的_isExecuting吗? The completion block should be called when _isFinished is set to YES and as far as I can see, I am doing that in the finish block. _isFinished设置为YES时,应该调用完成块,据我所知,我是在完成块中这样做的。 And the finish block is being called quite frequently as it should be. 而且,finish块应该经常被调用。

Any help, guidance or direction is appreciated. 任何帮助,指导或指示,我们感激不尽。 Please let me know if I have made any errors or if I have been less-than-clear in the post. 如果我有任何错误,或者帖子中的内容不够清楚,请告诉我。

Thanks, 谢谢,

From the NSOperation class reference : NSOperation类参考

An operation object is a single-shot object—that is, it executes its task once and cannot be used to execute it again. 操作对象是单发对象,即,它只执行一次任务,而不能再次用于执行它。

You are not allowed to invoke -start multiple times on a single operation object. 您不允许在单个操作对象上多次调用-start

Another thing, in your -finish method, you need to properly nest the -willChange... and -didChange... calls. 另一件事,在您的-finish方法中,您需要正确地嵌套-willChange...-didChange...调用。 That is, you need to call -didChange... in the reverse order of the -willChange... calls: 也就是说,你需要调用-didChange...在相反的顺序-willChange...电话:

[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];

_isExecuting = NO;
_isFinished = YES;

[self didChangeValueForKey:@"isFinished"];
[self didChangeValueForKey:@"isExecuting"];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM