在Bolts Framework中实现可以取消的任务(BFTask)

时间:2015-06-12 07:21:36

标签: ios nsoperation bolts-framework bftask

cancel对我很好,但我有一个抱怨:​​我还没有看到一个关于你应该如何// Somewhere else. MYCancellationToken *cancellationToken = [[MYCancellationToken alloc] init]; [obj doSomethingComplicatedAsync:cancellationToken]; // When you get bored... [cancellationToken cancel]; 任务的实例。有关该主题的全部文档可在their GitHub page上找到,其中包含一个除了我关心的部分之外的所有部分: 取消任务。

cancel

他们的代码片段后跟:

  

注意:取消令牌实现应该是线程安全的。

我想知道以下内容:

  1. 他们是否有充分理由不在BFTask界面上提供cancellationToken(s)方法?他们有一个属性,表示任务是否被取消,但没有办法取消它。
  2. 是否有充分理由说他们不会在BFTask本身上包含cancel属性?
  3. cancelAllOperations的实施是否与任务本身紧密相关?或者是NSOperationQueue的{​​{1}}
  4. 的一般实现方式

3 个答案:

答案 0 :(得分:7)

  1. 您可能知道,BFTaskFuture and Promises构造的实现:
    " future是变量的只读占位符视图,而promise是一个可写的单一分配容器,用于设置未来的价值" 基本上,BFTaskFuture:它是变量的只读占位符视图。
    BFTaskCompletionSource是一个承诺:它是一个可写的单一赋值容器,用于设置未来的值。 (或错误 - 或取消任务)
    BFTask公共接口保持只读状态,因此不允许您直接取消它。
  2. 这与上一个问题的答案相同:BFTask是只读的,表示只读值。公开取消令牌将允许您操纵任务,这与其性质相矛盾。
  3. 让我们来看看它:https://github.com/BoltsFramework/Bolts-iOS/blob/master/Bolts/Common/BFCancellationToken.m BFCancellationToken令牌只存储BFTask可以检查的状态。您的异步任务代码基本上可以定期检查cancellationRequested设置为true,这样您就可以手动取消任务。

    注意:Bolts Framework iOS docs说:"任务有点像JavaScript承诺"这可能令人困惑,因为它确实是一个未来。我认为它的Javascript起源只是错误的。

答案 1 :(得分:6)

在Bolts中有一个非常有用的取消令牌实现,但由于某种原因,它不会在头文件之外的所有文档中记录。关键是BFCancellationTokenSource的使用。您需要保留对BFCancellationTokenSource的引用,才能发出和取消BFCancellationToken

在我的示例中,我有一个名为cancellableFunction()的特定函数,它会连续发出一堆任务。如果在最后一次调用完成之前再次调用该函数,我希望取消上一次调用的未完成任务。

这里的关键是将token传递给每个continueWith函数调用。如果在token取消tokenSource,则未执行的successBlock将被执行。您还可以通过每个task.cancelled中的BFContinuationBlock检查取消状态(显然在成功功能块中为false)。

以下是一个例子:

class ViewController: UIViewController {

   ...

   // instance reference to tokenSource so that it can be cancelled by any function in the ViewController
   var tokenSource: BFCancellationTokenSource?

   ...

   func cancellableFunction() -> BFTask {

      // First cancel the previous token
      tokenSource?.cancel()
      // Replace the previous TokenSource with a new one
      tokenSource = BFCancellationTokenSource()
      // Issue new Token from the new TokenSource
      let token = tokenSource!.token

      return functionThatReturnsBFTask().continueWithSuccessBlock({ (task:BFTask) -> AnyObject? in

         ...

         return nil
      }, cancellationToken: token).continueWithExecutor(BFExecutor.mainThreadExecutor(), successBlock: { (task:BFTask) -> AnyObject? in

         ...

         return nil
      }, cancellationToken: token).continueWithBlock({ (task:BFTask) -> AnyObject? in

         // Here you can perform an actions you want to take on cancellation
         if task.cancelled {

         }

         ...

         return nil
      }, cancellationToken: token)
   }

   ...

}

答案 2 :(得分:3)

使用[self.bfTaskCancelationToken cancel];代码取消BFTask系列

注册BFCancellationTokenSource

self.bfTaskCancelationToken = [BFCancellationTokenSource cancellationTokenSource];
[self.bfTaskCancelationToken.token registerCancellationObserverWithBlock:^{
    NSLog(@"task hasbeen Cancelled.....");
    //Do stuff on cancelation task

} ];

实施系列BFTask

注意:有cancellationToken:self.bfTaskCancelationToken.token       [task continueWithBlock:^id(BFTask *task)

之后的代码
  [[[self showAlertProgressHud] continueWithBlock:^id(BFTask *taskLog) {


            BFTask *task = [BFTask taskWithResult:nil];
            for (int i=0; i<self.arrAssetPhotos.count; i++) {

                AIAssetPhoto *assetPhoto = self.arrAssetPhotos[i];
                task = [task continueWithBlock:^id(BFTask *task) {
                    // Return a task that will be marked as completed.
                    return [self processOnAssetPhoto:assetPhoto index:i completion:NULL];
                } cancellationToken:self.bfTaskCancelationToken.token];

            }

            return task;


        }] continueWithBlock:^id(BFTask *task) {

            // all asset photos process are done.
            return nil;
        }];

如何取消连续的BFtask?

  //just by calling one simple method 
  [self.bfTaskCancelationToken cancel];