我正在寻找一种被调用方可以在专用调度程序上执行的方法,并在执行后将调度程序恢复到调用方使用的调度程序。
使用的库和scala:
"io.monix" %% "monix" % "3.0.0-RC1"
"org.typelevel" %% "cats-core" % "1.0.1"
示例代码:
import monix.eval.Task
import monix.execution.Scheduler
import scala.concurrent.Await
import scala.concurrent.duration.Duration
import monix.execution.Scheduler.Implicits.global
import cats.implicits._
object Test extends App {
val io1 = Scheduler.io("io1")
val io2 = Scheduler.io("io2")
def taskEval(name: String) = Task.eval(println(s"Running eval Task [$name] on thread [${Thread.currentThread().getName}]"))
def subTask: Task[Unit] = {
taskEval("subTaskScope").executeOn(io2) <* Task.shift
}
val program1 = taskEval("outerScopeBefore").executeOn(io1) *> subTask *> taskEval("outerScopeAfter")
val program2 = (taskEval("outerScopeBefore") *> subTask *> taskEval("outerScopeAfter")).executeOn(io1)
val program3 = taskEval("outerScopeBefore").executeOn(io1) *> subTask *> taskEval("outerScopeAfter").executeOn(io1)
Await.result(program1.runAsync, Duration.Inf)
// Running eval Task [outerScopeBefore] on thread [io1-515]
// Running eval Task [subTaskScope] on thread [io2-516] // << the subTask changes the scheduler of the outerScope
// Running eval Task [outerScopeAfter] on thread [scala-execution-context-global-517] // << the scheduler jumps to the global default
println("-----")
Await.result(program2.runAsync, Duration.Inf)
// Running eval Task [outerScopeBefore] on thread [io1-515]
// Running eval Task [subTaskScope] on thread [io2-516]
// Running eval Task [outerScopeAfter] on thread [io1-515]
println("-----")
Await.result(program3.runAsync, Duration.Inf)
// Running eval Task [outerScopeBefore] on thread [io1-515]
// Running eval Task [subTaskScope] on thread [io2-516]
// Running eval Task [outerScopeAfter] on thread [io1-515]]
}
subTask
是被调用方,它想在专用调度程序上执行一些计算,但是它不想更改调用方中使用的调度程序。
很明显,subTask
可以使用executeOn(io2)
来指定要使用io2
,然后真诚地使用Task.shift
,这将带回调度程序在呼叫者中使用。问题是,除非调用者(即flatMap序列中的program1
)再次重置调度程序(如program2
)或设置它自己的“ default ”调度程序(如在program3
中,将subTask
移回 default 的良好意图恢复为最顶层的调度程序(在本例中为 global )。
因此,除非调用者采取了特殊的预防措施(如program2
或),否则被调用者实际上无法在专用调度程序上执行工作,而不会冒着更改用于其余执行调用程序的调度程序的风险。 program3
)。但是,即使呼叫者采取了这些预防措施,也只会将问题推高到将要呼叫program2
或program3
的那个问题上。
我想做的是使subTask
能够指定它要在专用调度程序(io2
)中执行,而无需更改调用方使用的调度程序。 subTask
。