7

BFTask对我很好,但我有一个抱怨:​​我还没有看到你应该如何完成cancel一项任务的工作示例。有关该主题的全部文档都可以在他们的 GitHub 页面上找到,其中只有一个低级部分,其中包括除我关心的部分之外的所有内容:如何取消任务。

// 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与任务本身强耦合?cancelAllOperations或者在 的情况下是否可以进行一般实现NSOperationQueue
4

3 回答 3

7
  1. 您可能知道,Future 和 Promises构造BFTask的一个实现: “future 是变量的只读占位符视图,而 Promise 是设置未来值的可写、单一赋值容器”。 基本上, a是 a :它是变量的只读占位符视图。 A是一个承诺:它是一个可写的、单一的赋值容器,用于设置未来的值。(或错误 - 或取消任务) 公共接口保持只读状态,因此不允许您直接取消它。

    BFTaskFuture
    BFTaskCompletionSource
    BFTask
  2. 这与上一个问题的答案相同:BFTask 是只读的,表示只读值。暴露取消令牌将允许您操纵任务,这与其性质相矛盾。
  3. 让我们看一下:https : //github.com/BoltsFramework/Bolts-iOS/blob/master/Bolts/Common/BFCancellationToken.mBFCancellationToken令牌只是存储一个状态,BFTask可以检查。您的异步任务代码基本上可以定期检查cancellationRequested设置为 true,这允许您手动取消您的任务。

    注意:Bolts Framework iOS文档说:“任务有点像 JavaScript Promise”,这可能会让人感到困惑,因为它确实是一个 Future。我认为它只是在其 Javascript 起源中命名错误。
于 2015-07-10T21:09:20.487 回答
7

Bolts 中有一个相当有用的取消标记实现,但由于某种原因,它根本没有记录在头文件之外。关键是BFCancellationTokenSource. 您需要保留对 的引用BFCancellationTokenSource才能发布和取消BFCancellationToken.

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

这里的关键是将 传递给token每个continueWith函数调用。如果在任何时候token通过 取消tokenSource, unreached 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)
   }

   ...

}
于 2016-03-18T02:36:20.490 回答
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];
于 2015-11-21T12:57:50.980 回答