繁体   English   中英

Minecraft spigot 插件中的 Kotlin 协程

[英]Kotlin coroutines in Minecraft spigot plugin

在文档中它说协程比线程轻,所以我想使用 kotlin 协程而不是 BukkitRunnable。

//Defined as class field
private val scope = coroutineScope(Dispatchers.Default)

//In class method
scope.launch {/* wait some seconds and then change blockdata */}

从 Dispatchers.Default 线程调用 setBlockData 会引发错误,因为 spigot API 不是线程安全的,并且您不能从主线程以外的线程调用 API 的东西。

java.lang.IllegalStateException: Asynchronous block remove!

我在想更改块数据相当于 Minecraft 中的 android UI 更改,这意味着协程需要运行/注入到主线程中。 所以在 Dispatchers.Main 中运行我的协程是有意义的。 但是,我找不到使用 Dispatchers.Main 并将其设置为主线程而不会得到非法状态异常的方法

我希望我的逻辑在这里是正确的

如果您想要一个能够将挂起代码与主线程桥接的简单方法(可以从主线程获取一些信息并在您的协程上使用),您可以使用此方法:

suspend fun <T> suspendSync(plugin: Plugin, task: () -> T): T = withTimeout(10000L) {
    // Context: The current coroutine context
    suspendCancellableCoroutine { cont ->
        // Context: The current coroutine context
        Bukkit.getScheduler().runTask(plugin) {
            // Context: Bukkit MAIN thread
            // runCatching is used to forward any exception that may occur here back to
            // our coroutine, keeping the exceptions transparency of Kotlin coroutines
            runCatching(task).fold({ cont.resume(it) }, cont::resumeWithException)
        }
    }
}

我已经评论了代码的每个部分执行的上下文,以便您可以可视化上下文切换。 suspendCancellableCoroutine是一种获取所有协程在后台使用的continuation object 的方法,因此我们可以在主线程执行我们的任务后手动恢复它。

外部块withTimeout用于如果主线程没有在 10 秒内完成我们的任务,我们的协程放弃而不是永远挂起。

而且使用也很简单:

val plugin = // comes from somewhere

// example coroutine scope
CoroutineScope(Dispatchers.Default).launch {
    // doing stuff async
    // oh no, I need some data from the main thread!
    val block = suspendSync(plugin) { 
        // this code runs on the MAIN thread
        Bukkit.getWorld("blah").getBlockAt(0, 0, 0) 
    }
    // back to async here, do stuff with block (just don't MODIFY it async, use more suspendSync if needed)
}

如果您有任何问题或事情我可以改进此答案,请不要害怕让我知道。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM