Multithreading 标签文本不是';即使UI线程似乎有响应,也不会更新

Multithreading 标签文本不是';即使UI线程似乎有响应,也不会更新,multithreading,kotlin,javafx-8,tornadofx,Multithreading,Kotlin,Javafx 8,Tornadofx,我正在JDK 8u121上使用Kotlin 1.1.51使用TornadFX 1.7.11构建一个应用程序 我试图在一个单独的线程中执行一个长时间运行的任务,并使用progressbar和标签在UI中显示进度。奇怪的是,标签没有更新。我想也许我在UI线程上运行了这个任务,但它被卡住了,但是progressbar可以工作,UI也可以响应(控件可以工作等等) 我还尝试过用ScenicView手动编辑标签,效果很好。我没主意了,你们能帮忙吗 以下是一些简化的代码片段: MainView.kt 主控制

我正在JDK 8u121上使用Kotlin 1.1.51使用TornadFX 1.7.11构建一个应用程序

我试图在一个单独的线程中执行一个长时间运行的任务,并使用progressbar和标签在UI中显示进度。奇怪的是,标签没有更新。我想也许我在UI线程上运行了这个任务,但它被卡住了,但是progressbar可以工作,UI也可以响应(控件可以工作等等)

我还尝试过用ScenicView手动编辑标签,效果很好。我没主意了,你们能帮忙吗

以下是一些简化的代码片段:

MainView.kt 主控制器
class MainController : Controller() {
    private val tasksController: TasksController by inject()

    fun reloadTranslations(): TaskStatus {
        val task = TaskStatus()
        tasksController.tasks.add(task)
        runAsync(task) {
            updateMessage(messages["loadingTranslations"])
            BibxCache.rebuild().subscribe {
                updateMessage(messages["loadingTranslations"] + " " + it.loaded)  // for debugging
                updateProgress(it.loaded.toLong(), it.total.toLong())
            }
        }
        return task
    }

    fun getTranslations() = BibxCache.values.toSortedSet()
}
TasksView.kt TasksController.kt
class TasksController : Controller() {
    val tasks: ObservableList<TaskStatus> = FXCollections.observableArrayList()

    init {
        tasks.onChange { change ->
            change.next()
            change.addedSubList.forEach { added ->
                added.completed.onChange {
                    tasks.remove(added)
                }
            }
        }
    }
}
class TasksController:Controller(){
val任务:ObservalElist=FXCollections.ObservalArrayList()
初始化{
tasks.onChange{change->
更改。下一个()
change.addedPublist.forEach{added->
added.completed.onChange{
任务。删除(添加)
}
}
}
}
}

您的代码不可运行,但我基于这些概念,使用更惯用的方法创建了一个最小的示例

class MainView : View("Tasks") {
    private val mainController: MainController by inject()

    override val root = borderpane {
        setPrefSize(600.0, 400.0)
        top {
            button("Start task").action {
                mainController.reloadTranslations()
            }
        }
        bottom(TasksView::class)
    }
}

class MainController : Controller() {
    private val tasksController: TasksController by inject()

    fun reloadTranslations(): TaskStatus {
        val task = TaskStatus()
        tasksController.tasks.add(task)
        runAsync(task) {
            updateMessage(messages["loadingTranslations"] + " $this...")
            Thread.sleep(Random().nextInt(2000).toLong())
            updateMessage(messages["loadingTranslations"] + " $this - half way")
            updateProgress(50.0, 100.0)
            Thread.sleep(Random().nextInt(2000).toLong())
        }
        return task
    }
}

class TasksView : View() {
    val controller: TasksController by inject()

    override val root = vbox {
        bindChildren(controller.tasks) { task ->
            hbox {
                progressbar(task.progress)
                label(task.message)
            }
        }
    }
}

class TasksController : Controller() {
    val tasks: ObservableList<TaskStatus> = FXCollections.observableArrayList()

    init {
        tasks.onChange { change ->
            change.next()
            change.addedSubList.forEach { added ->
                added.completed.onChangeOnce {
                    tasks.remove(added)
                }
            }
        }
    }
}
class主视图:视图(“任务”){
私有val mainController:mainController by inject()
覆盖val root=borderpane{
setPrefSize(600.0400.0)
顶{
按钮(“启动任务”)。操作{
mainController.reloadTranslations()
}
}
底部(TasksView::类)
}
}
类MainController:Controller(){
私有val tasksController:tasksController by inject()
fun reloadTranslations():任务状态{
val任务=任务状态()
tasksController.tasks.add(任务)
运行异步(任务){
updateMessage(消息[“loadingTranslations”]+“$this…”)
Thread.sleep(Random().nextInt(2000).toLong())
updateMessage(消息[“loadingTranslations”]+“$this-中途”)
updateProgress(50.01100.0)
Thread.sleep(Random().nextInt(2000).toLong())
}
返回任务
}
}
类TasksView:View(){
val控制器:通过注入的TasksController()
覆盖val root=vbox{
bindChildren(controller.tasks){task->
hbox{
progressbar(任务进度)
标签(task.message)
}
}
}
}
类TasksController:Controller(){
val任务:ObservalElist=FXCollections.ObservalArrayList()
初始化{
tasks.onChange{change->
更改。下一个()
change.addedPublist.forEach{added->
added.completed.onChangeOnce{
任务。删除(添加)
}
}
}
}
}

这也可以用较少的宣传来完成,但我不知道你的应用程序的复杂性或要求,所以我尽量少做改动:)

谢谢!我喜欢你的方法,它简洁易懂,效果如预期。很高兴听到:))
class TasksController : Controller() {
    val tasks: ObservableList<TaskStatus> = FXCollections.observableArrayList()

    init {
        tasks.onChange { change ->
            change.next()
            change.addedSubList.forEach { added ->
                added.completed.onChange {
                    tasks.remove(added)
                }
            }
        }
    }
}
class MainView : View("Tasks") {
    private val mainController: MainController by inject()

    override val root = borderpane {
        setPrefSize(600.0, 400.0)
        top {
            button("Start task").action {
                mainController.reloadTranslations()
            }
        }
        bottom(TasksView::class)
    }
}

class MainController : Controller() {
    private val tasksController: TasksController by inject()

    fun reloadTranslations(): TaskStatus {
        val task = TaskStatus()
        tasksController.tasks.add(task)
        runAsync(task) {
            updateMessage(messages["loadingTranslations"] + " $this...")
            Thread.sleep(Random().nextInt(2000).toLong())
            updateMessage(messages["loadingTranslations"] + " $this - half way")
            updateProgress(50.0, 100.0)
            Thread.sleep(Random().nextInt(2000).toLong())
        }
        return task
    }
}

class TasksView : View() {
    val controller: TasksController by inject()

    override val root = vbox {
        bindChildren(controller.tasks) { task ->
            hbox {
                progressbar(task.progress)
                label(task.message)
            }
        }
    }
}

class TasksController : Controller() {
    val tasks: ObservableList<TaskStatus> = FXCollections.observableArrayList()

    init {
        tasks.onChange { change ->
            change.next()
            change.addedSubList.forEach { added ->
                added.completed.onChangeOnce {
                    tasks.remove(added)
                }
            }
        }
    }
}