【发布时间】:2022-01-13 10:52:51
【问题描述】:
目前我有一个不断循环的主线程:
var suspension = Suspension()
fun loop() {
// Doing stuff here...
suspension.callTick()
// Doing more stuff here...
}
它调用 callTick() 方法将数据发送到通道:
class Suspension {
private val ticksChannel = Channel<Unit>(0)
fun callTick() {
ticksChannel.trySend(Unit)
}
suspend fun waitTick() {
ticksChannel.receive()
}
}
现在我的最后一堂课使用了这个:
class Task(private val suspension: Suspension) {
suspend fun runTask() {
while (true) {
suspension.waitTick()
someMethodOnTheMainThread()
}
}
}
现在我想知道如何从主线程调用 someMethodOnTheMainThread() 方法。该函数必须在 loop() 中的 'suspension.callTick()' 方法之后立即调用。目前我正在从协程线程运行该函数。这会导致很多错误和空指针异常,因为它没有与主线程同步。
基本上我想知道如何阻塞/锁定主线程,直到调用suspend.waitTick()方法并运行它之后的代码。这太复杂了吗?还有其他方法可以使挂起函数与同步代码一起使用吗?
【问题讨论】:
-
在挂起函数中,任何时候你使用一个只能从主线程访问的属性或函数,将它包装在
withContext(Dispatchers.Main) { }中。 -
这似乎只适用于Android:
Module with the Main dispatcher is missing. Add dependency providing the Main dispatcher, e.g. 'kotlinx-coroutines-android' and ensure it has the same version as 'kotlinx-coroutines-core' -
你在哪个平台上?有针对不同平台的协程库,例如 Swing 和 JavaFX,它们为它们提供 Dispatchers.Main。如果您不使用其中之一并且正在设计自己的主线程,则可以创建一个 Dispatchers.Main 来利用您自己的主线程队列。
-
我在 Windows 上。通过一些快速测试,似乎 Dispatchers.Unconfined 也可以正常工作。从我在原始帖子中给出的示例中,您是否会偶然知道这是否属实?对我来说它似乎很奇怪,因为它说即使在延迟之后线程也是主线程,从文档中它不应该这样做。如果它不起作用,我会尝试创建自己的 Dispatchers.Main。
-
我的意思是你的目标平台,例如摇摆,JavaFX,iOS,CLI。如果它是 CLI 并且主线程是您自己创建的,我认为您需要为它创建自己的调度程序。如果您希望它在特定线程上可靠地运行代码,Unconfined 将非常脆弱。
标签: kotlin concurrency coroutine synchronize