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

问题描述 投票:7回答:3

BFTask一直对我好,但我有一个抱怨:​​我还没有看到你应该如何cancel任务的一个工作的例子。关于这个主题的整个文档可以在their GitHub page上找到,其中包含一个低级部分,其中包括我关心的部分:如何取消任务。

// Somewhere else.
MYCancellationToken *cancellationToken = [[MYCancellationToken alloc] init];
[obj doSomethingComplicatedAsync:cancellationToken];

// When you get bored...
[cancellationToken cancel];

他们的代码片段后跟:

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

我想知道以下内容:

  1. 有没有充分的理由说他们可能没有在cancel界面上提供BFTask方法?他们有一个属性,表示任务是否被取消,但没有办法取消它。
  2. 有没有充分的理由说他们不会在cancellationToken(s)本身包含BFTask财产?
  3. cancel的实施是否与任务本身强烈耦合?或者是一般的实现,如cancelAllOperationsNSOperationQueue
ios nsoperation bolts-framework bftask
3个回答
7
投票
  1. 您可能知道,BFTaskFuture and Promises构造的实现: “未来是变量的只读占位符视图,而承诺是一个可写的单一赋值容器,用于设置未来的值”。 基本上,BFTaskFuture:它是变量的只读占位符视图。 BFTaskCompletionSource是一个承诺:它是一个可写的单一分配容器,它设定了未来的价值。 (或错误 - 或取消任务) BFTask公共接口仍然是只读的,因此它不允许您直接取消它。
  2. 这与前一个问题的答案相同:BFTask是只读的,表示只读值。公开取消令牌将允许您操纵任务,这与其性质相矛盾。
  3. 让我们来看看它:https://github.com/BoltsFramework/Bolts-iOS/blob/master/Bolts/Common/BFCancellationToken.m BFCancellationToken令牌只存储一个状态,BFTask可以检查。你的异步任务代码基本上可以定期检查cancellationRequested是否设置为true,这允许你手动取消你的任务。 注意:Bolts框架iOS docs说:“任务有点像JavaScript承诺”,这可能令人困惑,因为它确实是一个未来。我认为它的Javascript起源只是错误的。

7
投票

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

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

这里的关键是将token传递给每个continueWith函数调用。如果token在任何时候通过tokenSource取消,未得到的successBlocks将不会被执行。您还可以通过每个task.cancelled中的BFContinuationBlock检查取消状态(显然在成功块中为假)。

这是一个例子:

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)
   }

   ...

}

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];
© www.soinside.com 2019 - 2024. All rights reserved.