2015-06-12 14 views
6

BFTask była dla mnie dobra, ale mam jedną skargę: Nie widziałem jeszcze przykładu, jak powinieneś wykonać zadanie w postaci cancel. Cała dokumentacja na ten temat znajduje się pod numerem their GitHub page z pojedynczą, niską sekcją, która zawiera wszystko, ale część, na której mi zależy: , jak anulować zadanie.Realizacja zadań, które mogą być anulowane w ramach Rygiel (BFTask)

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

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

Ich fragment kodu następuje:

Uwaga: Odwołanie żeton realizacja powinna być bezpieczny wątku.

Zastanawiam się, co następuje:

  1. Czy istnieje dobry powód, że nie mogą one dostarczyły metody cancel na samym interfejsie BFTask? Mają właściwość reprezentującą, czy zadanie zostało anulowane, ale nie ma możliwości anulowania go.
  2. Czy istnieje uzasadniony powód, że nie będą one zawierać własności cancellationToken(s) na samej BFTask?
  3. Czy implementacja cancel jest silnie powiązana z samym zadaniem? Czy możliwe jest ogólne wdrożenie, jak w przypadku cancelAllOperations z NSOperationQueue?

Odpowiedz

6
  1. Jak pewnie wiesz, BFTask jest realizacja Future and Promises konstruktem:
    „przyszłość jest tylko do odczytu zastępczy Widok zmiennej, a obietnica jest zapisywalny, pojedynczy pojemnik przypisanie który ustawia wartość przyszłości ".
    Zasadniczo, BFTask to Future: jest to widok zastępczy zmiennej tylko do odczytu.
    A BFTaskCompletionSource to obietnica: jest to zapisywalny, pojedynczy pojemnik przydziału, który określa wartość przyszłości. (lub błąd - lub anuluje zadanie)
    Interfejs publiczny BFTask pozostaje tylko do odczytu, dlatego nie pozwala na bezpośrednie anulowanie.
  2. To ma taką samą odpowiedź jak poprzednie pytanie: BFTask jest tylko do odczytu i reprezentuje wartość tylko do odczytu. Ujawnienie żetonów anulowania umożliwiłoby manipulowanie zadaniem, co jest sprzeczne z jego charakterem.
  3. Spójrzmy na to: https://github.com/BoltsFramework/Bolts-iOS/blob/master/Bolts/Common/BFCancellationToken.m Znacznik BFCancellationToken po prostu przechowuje stan, który można sprawdzić przez BFTask. Twój asynchroniczny kod zadania może zasadniczo regularnie sprawdzać, czy cancellationRequested jest ustawiony na wartość true, co umożliwia ręczne anulowanie zadania.
    Uwaga: The Bolts Framework iOS docs mówi: "Zadanie jest podobne do obietnicy JavaScript", co może być mylące, ponieważ tak naprawdę jest to przyszłość. Myślę, że został on nazwany błędnie w swoich źródłach Javascript.
2

Użyj kodu [self.bfTaskCancelationToken cancel]; anulować serię BFTask

// --------- Rejestracja BFCancellationTokenSource -------------------- -------

self.bfTaskCancelationToken = [BFCancellationTokenSource cancellationTokenSource]; 
     [self.bfTaskCancelationToken.token registerCancellationObserverWithBlock:^{ 

      NSLog(@"task hasbeen Cancelled....."); 
      //Do stuff on cancelation task 

    } ]; 

// ---------------- Wykonanie serii BFTask --------------- ---------------------------

Uwaga: istnieje kod cancellationToken:self.bfTaskCancelationToken.token po [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; 
     }]; 

// --------- Jak anulować ciągłe BFtask? -------------------

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

Jest to dość przydatna wdrażanie tokenów rezygnacji na śruby, ale z jakiegoś powodu nie jest to udokumentowane w ogóle poza plików nagłówkowych. Kluczem jest użycie BFCancellationTokenSource. Aby wydać i anulować BFCancellationToken, musisz zachować odniesienie do numeru BFCancellationTokenSource.

W moim przykładzie mam konkretną funkcję o nazwie cancellableFunction(), która wydaje szereg zadań z rzędu. Jeśli funkcja zostanie wywołana ponownie przed zakończeniem ostatniego połączenia, chcę anulować niezakończone zadania poprzedniego połączenia.

Kluczem tutaj jest przekazanie token do każdego wywołania funkcji continueWith. Jeśli w dowolnym momencie token zostanie anulowane za pośrednictwem tokenSource, nieużywane successBlock s nie zostaną wykonane. Możesz również sprawdzić status anulowania przez task.cancelled w każdym BFContinuationBlock (oczywiście będzie to wartość false w blokach sukcesu).

Oto przykład:

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

    ... 

} 
Powiązane problemy