Przyglądałem się tej prezentacji https://github.com/indyscala/scalaz-task-intro/blob/master/presentation.md i był zdezorientowany jednym z fragmentów kodu, które przedstawiono za pomocą Task.runAsyncInterruptibly (nieznacznie zmodyfikowane pojawia się poniżej):
import java.util.concurrent.atomic.AtomicBoolean
import scalaz.concurrent.Task
import scalaz.{-/, /-}
object Junk extends App {
val neverMind = new AtomicBoolean(false)
System.out.println(s"neverMind set to $neverMind on thread ${Thread.currentThread().getName}")
val t = Task {
System.out.println(s" in task run block on thread ${Thread.currentThread().getName}")
Thread.sleep(4000)
System.out.println(s" completed sleep of 40000 ms on thread ${Thread.currentThread().getName}")
}
Task.fork(t).
//t.
runAsyncInterruptibly({
case -/(t) => t.printStackTrace()
case /-(()) => println(s"Completed (right) branch of case on thread ${Thread.currentThread().getName}")
}, neverMind)
println("sleeping 1000, then set nevermind to true")
Thread.sleep(1000)
neverMind.set(true)
println("woke up. set cancel=true -- expect stack trace not "Completed" message")
Thread.sleep(4000)
}
Jestem zdziwiony, ponieważ ustawiam flagę "anuluj"(neverMind.set (true)), ale nie widzę śladu stosu, blok kodu wewnątrz opóźnienia {...} ostatecznie drukuje "zakończony pomyślnie." To jest takie proste, jestem pewien, że robię głupi błąd .. nie wiem gdzie!
Szukałem porady od niektórych kolegów, którzyzauważyłem, że mój oryginalny przykład nie użył Task.fork (), więc robiłem wszystko w tym samym wątku ... doh! DOBRZE. poprawiłem to. i nadal nie działa.
Z góry dziękuję za wszelkie wskazówki, które możesz podać.
Odpowiedzi:
1 dla odpowiedzi № 1Myślę, że odpowiedź ma związek z trampoliningiem w Zadaniu / Przyszłości, ponieważ sprawdza tylko cancel
pomiędzy etapami (patrz listenInterruptibly
wewnątrz skalazu Future
.
Jeśli zmienisz zadanie na:
val t = Task.delay(System.out.println(s" in task run block on thread ${Thread.currentThread().getName}"))
.map(_ => Thread.sleep(4000))
.map(_ => System.out.println(s" completed sleep of 40000 ms on thread ${Thread.currentThread().getName}"))
zobaczysz, że zostanie anulowane przed zakończeniem "uśpienia", ale nadal nie wywoływał procedury obsługi, która wypisuje ślad stosu.