NSOperationQueue完成通知之前完成任务 - NSOperationQueue gets complete notification before completing tasks

- 此内容更新于:2015-12-13
主题:

在我的应用程序中,我使用子类会在单个操作4任务之后,我希望所有这四个任务运行在后台线程所以我包装成单一NSOperation类,这样我可以很容易地暂停或取消任务长时间运行计算获取的数据核心数据更新到服务器更新coredata这里每个执行同步,这意味着每一个都是依赖于另一个除了长时间运行计算。代码我假设我不遵循适当的方法,因为当我测试这段代码使用它到达之前完成通知计算完成。问题我的方法是正确的?如果不是,你能指引我正确的方法吗?如果这是正确的方法为何得到块完成执行之前完成通知?提前谢谢!期待你的反应

原文:

I am using NSOperation subclass in my app which will do following 4 tasks in a single operation, i wanted all these 4 tasks to run on background thread so I wrapped up into single NSOperation class, so that I can easily either pause or cancel it

Tasks

  1. long time running calculation
  2. fetching data from core data
  3. Updating to server
  4. Updating coredata

here each has to execute synchronously which means each one is depend on another one except long time running calculation.

Code

// 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

I am assuming that I am not following proper approach because when I tested this code using KVO the NSOperationQueuegets complete notification before it reaches calculate's completion block.

Questions

  1. Is my approach right?
  2. If not, can you some please guide me the right approach?
  3. If it is right approach then why does NSOPerationQueue get complete notification before completion block execution?

Thanks in advance! looking forward your response

网友:你处理取消如果这是异步操作,但没实现,也不做任何的或KVO。

(原文:You're handling cancellation as if this was asynchronous operation, but havent implemented isAsychronous, nor doing any of the isExecuting or isFinished KVO.)

网友:@Rob问题是:你为什么使用操作吗?AFNeworking已经提供了他们。

(原文:@Rob The question is: why do you use operations? AFNeworking already provides them under the hood.)

网友:@flexaddicted为什么操作?内很好地封装复杂的逻辑独立的对象。控制并发度。管理依赖性。等等。有很多的理由使用对象和我不会吝惜任何人谁想理解这个非常有用的模式。AFNetworking,虽然它并不是没有自己的缺陷,你是对的,它是强大的,并且应该被考虑。通知你,它只提供操作的模式,但不是的。

(原文:@flexaddicted Why operations? To nicely encapsulate complex logic within stand-alone object. To control degree of concurrency. To manage dependencies. Etc. There are lots of reasons to use NSOperation objects and I'm not going to begrudge anyone who wants to understand this incredibly useful pattern. Re AFNetworking, while it is not without its own flaws, you're right that it is it is strong, and should be considered. FYI, it only provides operation pattern within the NSURLConnection-based AFHTTPRequestOperationManager, but not within the NSURLSession-based AFHTTPSessionManager.)

网友:@Rob我的问题是关于抽象。换句话说,AFNetworking提供了一个抽象层次。所以,国际海事组织,不需要包装它在s。不管怎么说,是的。如果OP想了解优点使用操作,我同意你的评论。

(原文:@Rob My question was concerning about abstraction. In other words, AFNetworking provides a nice level of abstraction. So, IMO, there is no need to wrap it within NSOperations. Anyway, yes. If the OP wants to learn about pros about using operations, I agree your comment.)

网友:@flexaddicted同意了。对不起,我错过了你的观点。是的,当然,人们不应该重新发明轮子。AFNetworking是一个很好的起点。和OP也可以看看一个例子的来源一个适当的子类实现的样子(诚然,尽管一个复杂)。

(原文:@flexaddicted Agreed. Sorry, I missed your point. Yes, of course, one shouldn't reinvent the wheel. AFNetworking is a good place to start. And the OP can also look at the source for AFURLConnectionOperation for an example of what a proper NSOperation subclass implementation looks like (though, admittedly, a complex one).)

解决方案:
实际上只需要显式异步web调用您的操作将已经在后台线程上运行。所以你可以简化代码块结构没有太多的嵌套。然后你需要正确地构建操作子类处理异步内容,这里所描述的那样。
原文:

Only actually the web call needs to be explicitly asynchronous as your operation will already run on a background thread. So you can simplify the block structure in your code so there isn't so much nesting.

Then you need to properly construct your operation subclass to handle asynchronous content, as described here.

网友:仅供参考,链接现在有点过时的设置,不是。他还没有处理的取消请求。但它是一个体面的,如果过时,底漆的话题。我还参考OP子类化笔记NSOperation参考以及操作队列并发编程指南的章。

(原文:FYI, that link is a little dated nowadays you set isAsynchronous, not isConcurrent. He also doesn't handle the cancellation of a request in progress. But it's a decent, if dated, primer on the topic. I'd also refer OP to subclassing notes in NSOperation Reference as well as the operation queues chapter of the concurrency programming guide.)

解决方案:
performtask方法实际上并不执行任何任务。它分派任务队列或调用方法,调度任务队列。当调度完成,完成performtaskNSOperationQueue会把它完成,尽管仍在执行的任务。我不认为这里有太多理由使用NSOperation的。只使用肾小球囊性肾病。
原文:

The performTasks method doesn't actually perform any tasks. It dispatches tasks to queues or calls methods that dispatch tasks to queues. When the dispatching is done, performTasks is finished and your NSOperationQueue will treat it as finished, even though the task is still executing.

I don't think there's much reason to use NSOperation here. Just use GCD.

解决方案:
如果你想使用NSOperation只是遵循“北斗七星”回答你需要按顺序处理任务。你仍然可以和你一起去对付NSOperation使用肾小球囊性肾病和避免使用嵌套块结构。NSOperationvs中央调度
原文:

If you want to use NSOperation just follow "Wain's" answer you need process task sequentially.

You can still go with your nested block structure using GCD and avoiding use NSOperation.

NSOperation vs Grand Central Dispatch

网友:“块NSOperation不是一个好的选择。“不是真的。这是一个完全可以接受的模式。当然,有时肾小球囊性肾病的方法是适当的,但我其他情况下,操作队列的方法要好得多。它取决于因素超出了这个问题的范围。

(原文:"Block with NSOperation is not a good option." Not true. It's a perfectly acceptable pattern. Sure, sometimes GCD approach is adequate, but I other cases, operation queue approach is much better. It depends upon considerations beyond the scope of this question.)

网友:@Rob感谢输入。

(原文:@Rob Thanks for input.)