运行 R Shiny 中的后台进程
running background process in R Shiny
我写了一个脚本,如果按下按钮,它应该 运行 一个后台进程。过程完成后,我想进一步处理结果。
下面是我的脚本。此脚本中的过程是休眠 10 秒,然后检索当前文件夹中的文件名列表。后台进程位于函数 printLS() 中。这是由函数 r_bg().
在后台执行的
library(shiny)
library(callr)
ui <- fluidPage(
textOutput("clock"), br(),
actionButton("startjob","Start Job"), br(), br(),
uiOutput("LS")
)
server <- function(input, output, session)
{
output$clock <- renderText({
invalidateLater(1)
format(Sys.time(), "%d %b %H:%M:%S")
})
global <- reactiveValues(result = NULL)
printLS <- function() {
Sys.sleep(10)
result <- system2(
command = "ls",
args = c("-l"),
stdout = TRUE,
stderr = TRUE
)
}
observeEvent(input$startjob, {
global$result <- r_bg(func = printLS, supervise = F)
global$result$wait()
})
output$LS <- renderUI({
req(global$result)
if (!global$result$is_alive())
p(HTML(paste(global$result$get_result(), sep = "", collapse = "<br>")))
})
}
shinyApp(ui = ui, server = server)
应用程序中还显示了一个时钟。不幸的是,当后台进程 运行ning 时时钟停止 运行ning。我希望时钟在后台进程中继续 运行。我通过删除 'global$result$wait()' 进行了尝试。但随后它会查看后台进程是否永远 运行ning 而不会提供任何输出(即当前文件夹中的文件列表)。
我现在的问题是:如何让时钟在后台进程 运行ning 时继续?
如示例 here 中所述,wait()
意味着我们必须等待后台作业的结果才能继续其余过程。
在 运行 后台作业时保持时钟更新的一种方法是使用 poll_io()
检查作业是否完成(请注意,使用 poll_io()
比使用 poll_io()
更好is_alive()
,如本Github comment). I have done something similar in this 所述,虽然一般的app稍微复杂一些。
这是您需要在服务器中修改的内容:
observeEvent(input$startjob, {
global$result <- r_bg(func = printLS, supervise = F)
})
output$LS <- renderUI({
req(input$startjob)
if (global$result$poll_io(0)["process"] == "timeout") {
invalidateLater(1000)
} else {
p(HTML(paste(global$result$get_result(), sep = "", collapse = "<br>")))
}
})
请注意,system2(command = "ls", args = c("-l"), stdout = TRUE, stderr = TRUE)
在我的笔记本电脑上不起作用,所以我改用 system("ls -l")
。
我写了一个脚本,如果按下按钮,它应该 运行 一个后台进程。过程完成后,我想进一步处理结果。
下面是我的脚本。此脚本中的过程是休眠 10 秒,然后检索当前文件夹中的文件名列表。后台进程位于函数 printLS() 中。这是由函数 r_bg().
在后台执行的library(shiny)
library(callr)
ui <- fluidPage(
textOutput("clock"), br(),
actionButton("startjob","Start Job"), br(), br(),
uiOutput("LS")
)
server <- function(input, output, session)
{
output$clock <- renderText({
invalidateLater(1)
format(Sys.time(), "%d %b %H:%M:%S")
})
global <- reactiveValues(result = NULL)
printLS <- function() {
Sys.sleep(10)
result <- system2(
command = "ls",
args = c("-l"),
stdout = TRUE,
stderr = TRUE
)
}
observeEvent(input$startjob, {
global$result <- r_bg(func = printLS, supervise = F)
global$result$wait()
})
output$LS <- renderUI({
req(global$result)
if (!global$result$is_alive())
p(HTML(paste(global$result$get_result(), sep = "", collapse = "<br>")))
})
}
shinyApp(ui = ui, server = server)
应用程序中还显示了一个时钟。不幸的是,当后台进程 运行ning 时时钟停止 运行ning。我希望时钟在后台进程中继续 运行。我通过删除 'global$result$wait()' 进行了尝试。但随后它会查看后台进程是否永远 运行ning 而不会提供任何输出(即当前文件夹中的文件列表)。
我现在的问题是:如何让时钟在后台进程 运行ning 时继续?
如示例 here 中所述,wait()
意味着我们必须等待后台作业的结果才能继续其余过程。
在 运行 后台作业时保持时钟更新的一种方法是使用 poll_io()
检查作业是否完成(请注意,使用 poll_io()
比使用 poll_io()
更好is_alive()
,如本Github comment). I have done something similar in this
这是您需要在服务器中修改的内容:
observeEvent(input$startjob, {
global$result <- r_bg(func = printLS, supervise = F)
})
output$LS <- renderUI({
req(input$startjob)
if (global$result$poll_io(0)["process"] == "timeout") {
invalidateLater(1000)
} else {
p(HTML(paste(global$result$get_result(), sep = "", collapse = "<br>")))
}
})
请注意,system2(command = "ls", args = c("-l"), stdout = TRUE, stderr = TRUE)
在我的笔记本电脑上不起作用,所以我改用 system("ls -l")
。