/ / zastanawiasz się, dlaczego scalaz Task.runAsyncInterruptibly nie przerywa, jak bym tego oczekiwał - scala, concurrency, task, scalaz

Zastanawiasz się, dlaczego nie jest tak, że przerywam Task.runAsync nie przerywa, jak bym tego oczekiwał - scala, concurrency, task, scalaz

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 № 1

Myś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.