想知道为什么 scalaz Task.runAsyncInterruptibly 没有像我期望的那样打扰

wondering why scalaz Task.runAsyncInterruptibly not interrupting as i would expect it to

我一直在看这个演示文稿 https://github.com/indyscala/scalaz-task-intro/blob/master/presentation.md 并且对它使用 Task.runAsyncInterruptibly 呈现的代码片段之一感到困惑(略微修改如下所示):

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)

}

我很困惑,因为我设置了 'cancel' 标志 (neverMind.set(true)),但我没有看到堆栈跟踪。 delay {...} 内的代码块最终打印 'completed successfully'。这很简单,我确定我犯了一个愚蠢的错误..但不确定在哪里!

我向一些同事征求意见,他们指出我原来的例子没有使用 Task.fork() 所以我在同一个线程上做所有事情......哦!好的。我纠正了这一点。还是不行。

提前感谢您提供的任何指导。

我认为答案与 scalaz 的 Task/Future 内的蹦床有关​​,因为它只检查步骤之间的 cancel(参见 scalaz 的 Future 内的 listenInterruptibly

如果您将任务更改为:

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

您会看到它在 "completed sleep" 步骤之前被取消。不过,它似乎仍然没有调用打印堆栈跟踪的处理程序。