在 ktor 请求处理程序中启动协程
Posted
技术标签:
【中文标题】在 ktor 请求处理程序中启动协程【英文标题】:Launching coroutine in ktor request handler 【发布时间】:2021-12-10 06:07:31 【问题描述】:我想立即响应客户端并通过启动协程在后台处理请求。首先我尝试了以下解决方案:
suspend fun PipelineContext<Unit, ApplicationCall>.handleTest(value: Unit)
// insert calls to suspending functions here
launch
repeat(10000)
println("Executing background task $it.")
delay(1000)
call.respond("Executing the task in background")
routing
get("/test", PipelineContext<Unit, ApplicationCall>::handleTest)
这按预期工作。它立即返回并执行后台任务。 不过,IntelliJ IDE 给了我以下警告:
Ambiguous coroutineContext due to CoroutineScope receiver of suspend function
我知道这个警告的含义以及它发生的原因,所以我试图找到解决这个问题的方法:
suspend fun handleTest(context: PipelineContext<Unit, ApplicationCall>)
// insert calls to suspending functions here
context.launch
repeat(10000)
println("Executing background task $it.")
delay(1000)
context.call.respond("Executing the task in background")
routing
get("/test")
handleTest(this)
这段代码也可以按预期工作,但是在阅读本文https://elizarov.medium.com/explicit-concurrency-67a8e8fd9b25 时,我觉得它是错误的。作者解释说,除非将其包装在新的 coroutineScope
中,否则不应在挂起函数中启动协程。
我很好奇,尝试内联handleTest
:
routing
get("/test")
// insert calls to suspending functions here
launch
repeat(10000)
println("Executing background task $it.")
delay(1000)
call.respond("Executing the task in background")
这也按预期工作,甚至警告也消失了。但是,该构造在理论上仍然与第一个解决方案中的相同。
我的问题的正确解决方案是什么?
【问题讨论】:
【参考方案1】:我建议创建一个新的协程作用域,以明确coroutineContext
的取用位置,因为CoroutineScope
和suspend 函数都有它。
suspend fun PipelineContext<Unit, ApplicationCall>.handleTest(value: Unit) = coroutineScope
// insert calls to suspending functions here
launch
repeat(10000)
println("Executing background task $it.")
delay(1000)
call.respond("Executing the task in background")
【讨论】:
【参考方案2】:你可以使用 CoroutineScope:
routing
get("/test")
// insert calls to suspending functions here
CoroutineScope(Job()).launch
repeat(10000)
println("Executing background task $it.")
delay(1000)
call.respond("Executing the task in background")
它将创建一个新的范围解耦处理程序上下文。
【讨论】:
以上是关于在 ktor 请求处理程序中启动协程的主要内容,如果未能解决你的问题,请参考以下文章