zoukankan      html  css  js  c++  java
  • NSOperation以及NSOperationQueue的使用

    本文于2015.11.22进行了修改。

    1. 什么NSOperation

    NSOperation为控制任务状态、优先级、依赖关系以及任务管理提供了一种线程安全的结构。可以通过调用start方法来手动启动一个任务,或者把它加入到NSOperationQueue中,当它到达队列头部时自动启动。

    2. NSOperation的三个执行状态

    isReadyisExecutingisFinished是NSOperation生命周期中的三个互斥的状态。官方文档中关于NSOperation状态维护的说明非常详细:


    3. Synchronous和Asynchronous类型的NSOperation

    1. synchronous vs asynchronous的区别:
      In a synchronous operation, the operation object does not create a separate thread on which to run its task.
      An asynchronous operation object is responsible for scheduling its task on a separate thread. The operation could do that by starting a new thread directly, by calling an asynchronous method, or by submitting a block to a dispatch queue for execution.
    2. synchronous vs asynchronous的使用选择:
      If you always plan to use queues to execute your operations, it is simpler to define them as synchronous.
      When you add an operation to an operation queue, the queue ignores the value of the asynchronous property and always calls the start method from a separate thread. Therefore, if you always run operations by adding them to an operation queue, there is no reason to make them asynchronous.
      If you execute operations manually, though, you might want to define your operation objects as asynchronous.
      Defining an asynchronous operation requires more work, because you have to monitor the ongoing state of your task and report changes in that state using KVO notifications. But defining asynchronous operations is useful in cases where you want to ensure that a manually executed operation does not block the calling thread.

    4. NSOperation和NSOperationQueue的系统实现

    在介绍后面的小节之前,为了便于说吗,我们先约定两个词:
    终止任务=设置executingfinished属性的值,
    clean up=停止实际的图片下载、数据处理等操作。

    NSOperation中一些方法的系统实现:

    1. start方法:首先检查cancelled属性和finished属性(我认为没有必要检查isFinished属性),如果有一个为YES的话,立即终止任务;如果都为NO, 则修改executing属性的值,调用main方法
    2. cancel方法: 如果NSOperation不在队列里的话, 则立即终止任务;如果在队列里的话,则仅设置cancelledready属性的值,等待queue调用它的start方法时终止任务(如果cancel时尚未start),或者当它的其他方法执行中检查cancelled变量时终止任务(如果cancel时已经start)
    3. main方法:什么也不做

    NSOperationQueue中一些方法的系统实现:

    1. cancelAllOperations: 对queue中的每个operation调用cancel方法

    5. Subclassing NSOperation

    The NSOperation class provides the basic logic to track the execution state of your operation but otherwise must be subclassed to do any real work.

    1. 子类化Synchronous operation
      For non-concurrent operations, you typically override only one method: main. Into this method, you place the code needed to perform the given task.
      一个例子是:http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues

    2. 子类化Asynchronous operation
      If you are creating a concurrent operation, you need to override the following methods and properties at a minimum:

      • start: responsible for starting the operation in an asynchronous manner; should also update the execution state of the operation as reported by the executing property; should also check to see if the operation itself was cancelled before actually starting the task.
        At no time in your start method should you ever call super. When you define a concurrent operation, you take it upon yourself to provide the same behavior that the default start method provides.
      • asynchronous: YES
      • executing: Your executing property must also provide the status in a thread-safe manner.
      • finished: Your finished property must also provide the status in a thread-safe manner.

      Upon completion or cancellation of its task, your concurrent operation object must generate KVO notifications for both the isExecuting and isFinished key paths to mark the final change of state for your operation.In addition to generating KVO notifications, your overrides of the executing and finishedproperties should also continue to report accurate values based on the state of your operation.

    6. 响应取消命令

    关于如何响应取消NSOperation的操作,苹果官方文档上是这么建议的: 在NSOperation子类的所有方法中,任何耗时的操作之后都检查cancelled属性的值。如果为YES的话,终止任务,并设置executingfinished属性的值。 不需要重写cancel方法。这个例子也是这么处理的。

    但是在实际操作中,按照上述做法,当用户调用了cancel方法取消某个操作时并不能实时停止任务。因此,通常的做法是:

    • start方法:首先检查cancelled属性。如果为YES的话,立即终止任务;否则修改executing属性的值,开启任务
    • cancel方法:立即clean up, 并设置cancelled为YES,(如果你自己管理ready属性,那么也设置ready为YES),等待queue调用它的start方法时终止任务(如果cancel时尚未start),或者直接终止任务(如果cancel时已经start

    可以看出,上面两个方法的实现基本是对系统实现的重复,只不过增加了与用户任务相关的clean up操作。

    需要注意的是,对于一个在NSOperationQueue中的NSOperation,如果它尚未start, 那么不允许把它的finished属性设置成YES。 也就是说,必须依次经过了readyexecuting这两个状态之后,才能变为finished状态

    5. ASI的一个bug

    最近在跟进项目中遇到的ASI(版本为:v1.8.1-61 2011-09-19)在弱网情况下crash的问题, 发现在cancel满足以下三个条件的ASIHTTPRequest时必现crash:

    1. 在queue中
    2. 尚未start
    3. cache中有关于该请求的有效缓存,且该请求的策略允许从缓存中读取

    原因就在于在这种路径上直接将ASIHTTPRequest的isFinished设置成为了YES, 违背了本文第2节中提到的第二点注意事项。
    修改之后,一个ASIHTTPRequest的状态转换如下:

    注意:在ASI早期的版本中,有过类似的, cancel掉queue里一个尚未start的请求时crash的bug. 可以参考http://stackoverflow.com/questions/3291834/asihttprequest-dealloc-and-exc-bad-access-problem

    Refs

    http://nshipster.com/nsoperation/
    https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOperation_class/#//apple_ref/doc/uid/TP40004591-RH2-SW18
    http://stackoverflow.com/questions/3291834/asihttprequest-dealloc-and-exc-bad-access-problem
    http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues

  • 相关阅读:
    spring和mybatis整合配置文件
    点击不同按钮,加载不同的页面(不使用iframe的情况下)
    两个完整的jquery slide多方面滑动效果实例
    autofac无法解析一例
    c# Random太快产生的随机数会重复
    linq和ef关于group by取最大值的两种写法
    JavaScript 汉字与拼音互转终极方案 附JS拼音输入法
    使用USB Key(加密狗)实现身份认证
    让Dreamweaver支持cshtml (MVC Razor环境)
    使用EF扩展EntityFramework.BulkInsert实现批量插入
  • 原文地址:https://www.cnblogs.com/mindyme/p/4953270.html
Copyright © 2011-2022 走看看