【问题标题】:NSOperationOperationQueue cancelAllOperations method won't stop operationsNSOperationOperationQueue cancelAllOperations 方法不会停止操作
【发布时间】:2017-10-13 10:42:12
【问题描述】:

如何取消NSOperationQueue中的所有操作?我用了cancelAllOperations方法,但是没用,NSOperationQueue还在调用服务器上传照片。

我将每个连接都放在带有循环的 NSOperationQueue 上。

- (void)sendingImage:(NSArray *)imgArray compression:(CGFloat)compression
{    
    hud = [MBProgressHUD showHUDAddedTo: self.view animated: YES];
    hud.label.text = [NSString stringWithFormat: @"Waiting for Loading"];
    [hud.button setTitle: @"Cancel" forState: UIControlStateNormal];
    [hud.button addTarget: self action: @selector(cancelWork:) forControlEvents: UIControlEventTouchUpInside];

    __block int photoFinished = 0;

    self.queue = [[NSOperationQueue alloc] init];
    self.queue.maxConcurrentOperationCount = 5;
    [self.queue addObserver: self forKeyPath: @"operations" options: 0 context: NULL];

    NSBlockOperation *operation = [[NSBlockOperation alloc] init];
    __weak NSBlockOperation *weakOperation = operation;    
    __block NSString *response = @"";

    for (int i = 0; i < imgArray.count; i++) {

        operation = [NSBlockOperation blockOperationWithBlock:^{
            [self uploadingPhoto];
        }];

        [operation setCompletionBlock:^{
            NSLog(@"Operation 1-%d Completed", i);
            photoFinished++;

            dispatch_async(dispatch_get_main_queue(), ^{
                hud.label.text = [NSString stringWithFormat: @"%d photo complete uploading", photoFinished];
            });
        }];

        [self.queue addOperation: operation];
    }
}

我想按MBProgressHUD上的取消按钮,先取消所有的NSURLSessionDataTask,然后再取消所有的操作,但是没有用。

- (void)cancelWork:(id)sender {
    NSLog(@"cancelWork");    
    NSLog(@"self.queue.operationCount: %lu", (unsigned long)self.queue.operationCount);

    [session getTasksWithCompletionHandler:^(NSArray<NSURLSessionDataTask *> * _Nonnull dataTasks, NSArray<NSURLSessionUploadTask *> * _Nonnull uploadTasks, NSArray<NSURLSessionDownloadTask *> * _Nonnull downloadTasks) {

        if (!dataTasks || !dataTasks.count) {
            return;
        }
        for (NSURLSessionDataTask *task in dataTasks) {
            [task cancel];

            if ([self.queue operationCount] > 0) {
                [self.queue cancelAllOperations];
            }
        }
    }];
}

我用信号量让 NSURLSession 变成同步连接。

- (void)uploadingPhoto {

    request setting above

    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    config.timeoutIntervalForRequest = 1200;

    session = [NSURLSession sessionWithConfiguration: config];

    dataTask = [session dataTaskWithRequest: request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

        if (error == nil) {
            str = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
            NSLog(@"str: %@", str);
        }

        dispatch_semaphore_signal(semaphore);
    }];
    NSLog(@"task resume");
    [dataTask resume];

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    return str;
}

任何 cmets 或解决方案将不胜感激。

【问题讨论】:

    标签: ios cocoa nsurlsession nsoperationqueue


    【解决方案1】:

    NSOperation 默认不支持取消。请参阅类文档。一个摘录是:

    取消操作不会立即强制它停止正在执行的操作。尽管所有操作都需要尊重 cancelled 属性中的值,但您的代码必须显式检查此属性中的值并根据需要中止。

    使用NSBlockOperation 实现取消似乎也很困难。

    【讨论】:

    • 感谢您的快速回复。除了 NSBlockOperation 我还能用什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-21
    • 1970-01-01
    相关资源
    最近更新 更多