monix tasklocal在被来自不同词法作用域的任务引用时,似乎并不反映bind()调用的值

wribegjk  于 2021-07-14  发布在  Java
关注(0)|答案(1)|浏览(232)

我有一段代码,它是对scaladoc for tasklocal中给出的代码片段的一个轻微修改[原文如下:https://monix.io/api/3.0/monix/eval/tasklocal.html ].
我的代码只是将内联任务(在for construction中)替换为对在for construction范围外定义的任务的引用。不幸的是,当我的任务运行时,它没有看到绑定,而是看到原始值(0)。我希望我稍加修改的代码(如下)能产生与scaladoc代码片段相同的结果。但出乎意料的是,我得到的是“值3:4”,而不是值3:200。我对tlocal的引用似乎得到了一个不同的threadish局部变量的“版本”,该变量初始化为默认值,对绑定一无所知。
代码

class MonixTests extends FlatSpecLike with Matchers {

  "TaskLocal" should "not make me sad " in {
    val tlocal: Task[TaskLocal[Int]] = TaskLocal(0)

    val readTask: Task[Int] =
      tlocal.flatMap {
        taskLocal: TaskLocal[Int] =>
          taskLocal.read.map{ i => i  * 2 }
      }

    val task: Task[Unit] =
      for {
        local <- tlocal
        value1 <- local.read // value1 == 0
        _ <- local.write(100)
        value2 <- local.read // value2 == 100
        value3 <- local.bind(200)(readTask)
        value4 <- local.read // value4 == 100
        _ <- local.clear
        value5 <- local.read // value5 == 0
      } yield {
        // Should print 0, 100, 400, 100, 0 -- but value3 is not 400, but 4
        println("value1: " + value1)
        println("value2: " + value2)
        println("value3: " + value3)
        println("value4: " + value4)
        println("value5: " + value5)
      }

    import monix.execution.Scheduler.Implicits.global
    implicit val opts = Task.defaultOptions.enableLocalContextPropagation
    task.runToFutureOpt

    println("    TRY AGAIN a slightly different way, but no success ;^( ")

    val task3: Task[Unit] =
      for {
        local <- tlocal
        value1 <- local.read // value1 == 0
        _ <- local.write(100)
        value2 <- local.read // value2 == 100
        value3 <- local.bind(200)(readTask)
        value44 <-  local.bind(200) (
          tlocal.flatMap {
            taskLocal: TaskLocal[Int] =>
              taskLocal.read.map{i => i  *  2}
          }
        )
        _ <- local.clear
        value5 <- local.read // value5 == 0
      } yield {
        // Should print 0, 100, 400, 100, 0 -- but value3 is not 400, but 4
        println("value1: " + value1)
        println("value2: " + value2)
        println("value3: " + value3)
        println("value4: " + value44)
        println("value5: " + value5)
      }

    task3.runToFutureOpt
  }

理论基础:
我之所以要这样做是因为我想将一个值绑定到我的线程本地,然后创建一个任务的Map链,其中一些任务提取线程本地的当前值,我知道它是由tasklocal“前置”的。而且,为了清楚起见,其中一些任务是在我的代码库的其他类中定义的,而不是内联在任何特定的理解范围内。
谢谢/克里斯

rmbxnbpk

rmbxnbpk1#

我现在很高兴,因为我知道了如何或多或少地做我想做的事。下面的解决方案使用直接向上的“local”而不是tasklocal。但它具有所需的效果,即绑定值(200)在引用线程局部变量“tlocal”的代码块中可见。
我真的不需要在“任务上下文”中做什么,所以这让我走上了正确的轨道。

"TaskLocal" should "not make me sad today" in {
    import monix.execution.misc.Local

    val tlocal = Local(0)

    def doubleTlocal: Int = {tlocal.get * 2}

    val value1 = tlocal.get // value1 == 0
    tlocal.update(100)
    val value2 = tlocal.get // value2 == 100
    val value3 = tlocal.bind(200)(doubleTlocal)
    val value4 = tlocal.get // value4 == 100

     tlocal.clear
    val value5 = tlocal.get // value5 == 0

    println("value1: " + value1)
    println("value2: " + value2)
    println("value3: " + value3)
    println("value4: " + value4)
    println("value5: " + value5)
  }

相关问题