【问题标题】:NSOperationQueue gets complete notification before completing tasksNSOperationQueue 在完成任务之前获得完成通知
【发布时间】:2015-01-26 07:47:09
【问题描述】:

我在我的应用程序中使用NSOperation 子类,它将在一个操作中执行以下 4 个任务,我希望所有这 4 个任务都在后台线程上运行,所以我将其封装到单个 NSOperation 类中,这样我就可以轻松暂停或取消它

任务

  1. 长时间运行计算
  2. 从核心数据中获取数据
  3. 正在更新到服务器
  4. 更新核心数据

这里每个都必须同步执行,这意味着除了长时间运行的计算之外,每个都依赖于另一个。

代码

// MyOperation.h
@interface MyOperation : NSOperation {
}
@property (nonatomic, getter = isCancelled) BOOL cancelled;
@end

// MyOperation.m
@implementation MyOperation

- (void)cancel
{
   @synchronized (self)
   {
     if (!self.cancelled)
     {
        [self willChangeValueForKey:@"isCancelled"];
        self.cancelled = YES;
        [webServiceOperation cancel]
        [self didChangeValueForKey:@"isCancelled"];
     }
   }
}

- (void)main {
   if ([self isCancelled]) {
    NSLog(@"** operation cancelled **");
    return;
   }    
   @autoreleasepool{
    [self performTasks];
   }
}
- (void)performTasks {

    [self calculate:^{

          if (self.isCancelled)
              return;

          [self fetchDataFromCoredata:^{

                if (self.isCancelled)
                    return;

                //I am using AFNetWorking for updateWebService task so it shall run on separate NSOperation so it would be like nested NSOPeration

                webServiceOperation = [self updateWebService:^{

                                            if (self.isCancelled)
                                            return;

                                            [self updateCoreData:^{

                                                  if (self.isCancelled)
                                                        return;
                                            }];
             }];
        }];


    }];

}
@end

我假设我没有遵循正确的方法,因为当我使用 KVO 测试此代码时,NSOperationQueue 在到达计算的完成块之前会收到完整通知。

问题

  1. 我的方法对吗?
  2. 如果没有,请您指导我正确的方法吗?
  3. 如果是正确的方法,那么为什么NSOPerationQueue 在完成块执行之前会收到完成通知?

提前致谢!期待您的回复

【问题讨论】:

  • 您正在处理取消,就好像这是异步操作一样,但还没有实现isAsychronous,也没有执行任何isExecutingisFinished KVO。
  • @Rob 问题是:你为什么使用操作? AFNeworking 已经在后台提供了它们。
  • @flexaddicted 为什么操作?将复杂的逻辑很好地封装在独立对象中。控制并发度。管理依赖项。等等。有很多理由使用NSOperation 对象,我不会嫉妒任何想要理解这个非常有用的模式的人。 Re AFNetworking,虽然它并非没有自己的缺陷,但你是对的,它很强大,应该考虑。仅供参考,它仅在基于NSURLConnectionAFHTTPRequestOperationManager 内提供操作模式,但不在基于NSURLSessionAFHTTPSessionManager 内提供操作模式。
  • @Rob 我的问题是关于抽象的。换句话说,AFNetworking 提供了一个很好的抽象级别。所以,IMO,没有必要将它包装在NSOperations 中。无论如何,是的。如果 OP 想了解有关使用操作的专业人员,我同意您的评论。
  • @flexaddicted 同意。对不起,我错过了你的意思。是的,当然,不应该重新发明轮子。 AFNetworking 是一个很好的起点。并且 OP 还可以查看 AFURLConnectionOperation 的源代码,以了解正确的 NSOperation 子类实现是什么样的示例(虽然,诚然,这是一个复杂的实现)。

标签: ios objective-c objective-c-blocks nsoperation nsoperationqueue


【解决方案1】:

实际上只有网络调用需要显式异步,因为您的操作已经在后台线程上运行。因此,您可以简化代码中的块结构,从而减少嵌套。

然后你需要正确构造你的操作子类来处理异步内容,如here所述。

【讨论】:

  • 仅供参考,现在你设置的链接有点过时isAsynchronous,而不是isConcurrent。他也不处理正在进行的请求的取消。但它是一个不错的,如果过时的,关于这个话题的入门书。我还将 OP 参考 NSOperation Reference 中的子类化注释以及并发编程指南的操作队列章节。
【解决方案2】:

performTasks 方法实际上并不执行任何任务。它将任务分派到队列或调用将任务分派到队列的方法。调度完成后, performTasks 完成,您的 NSOperationQueue 将其视为已完成,即使任务仍在执行。

我认为这里没有太多理由使用 NSOperation。只需使用 GCD。

【讨论】:

    【解决方案3】:

    如果您想使用 NSOperation,只需按照“Wain”的回答,您需要按顺序处理任务。

    您仍然可以使用 GCD 使用嵌套块结构并避免使用 NSOperation。

    NSOperation vs Grand Central Dispatch

    【讨论】:

    • "使用 NSOperation 阻止不是一个好的选择。"不对。这是一个完全可以接受的模式。当然,有时 GCD 方法就足够了,但在其他情况下,操作队列方法要好得多。这取决于超出此问题范围的考虑。
    • @Rob 感谢您的意见。
    猜你喜欢
    • 2010-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-16
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    相关资源
    最近更新 更多