运行 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")