r - 是否可以停止在 Shiny 的内部执行 R 代码(不停止 Shiny 的进程)?

标签 r shiny

假设我有一个 Shiny 的应用程序,它的功能可能需要很长时间才能运行。是否可以有一个“停止”按钮来告诉 R 停止长时间运行的调用,而不必停止应用程序?

我的意思的例子:

analyze <- function() {
  lapply(1:5, function(x) { cat(x); Sys.sleep(1) })
}

runApp(shinyApp(
  ui = fluidPage(
    actionButton("analyze", "Analyze", class = "btn-primary"),
    actionButton("stop", "Stop")
  ),
  server = function(input, output, session) {
    observeEvent(input$analyze, {
      analyze()
    })
    observeEvent(input$stop, {
      # stop the slow analyze() function
    })
  }
))

编辑:x-post from shiny-discuss

最佳答案

所以另一个答案,在循环之外:使用子进程。

library(shiny)
library(parallel)

#
# reactive variables
# 
rVal <- reactiveValues()
rVal$process <- NULL
rVal$msg <- NULL
rVal$obs <- NULL
counter <- 0
results <- list()
dfEmpty <- data.frame(results = numeric(0))


#
# Long computation
#
analyze <- function() {
  out <- lapply(1:5, function(x) {
    Sys.sleep(1)
    rnorm(1)
})
  data.frame(results = unlist(out))
}

#
# Shiny app
#
shinyApp(
  ui = fluidPage(
    column(6,
      wellPanel(
        tags$label("Press start and wait 5 seconds for the process to finish"),
        actionButton("start", "Start", class = "btn-primary"),
        actionButton("stop", "Stop", class = "btn-danger"),
        textOutput('msg'),
        tableOutput('result')
        )
      ),
    column(6,
      wellPanel(
        sliderInput(
          "inputTest",
          "Shiny is responsive during computation",
          min = 10,
          max = 100,
          value = 40
          ),
        plotOutput("testPlot")
        ))),
  server = function(input, output, session)
  {
    #
    # Add something to play with during waiting
    #
    output$testPlot <- renderPlot({
      plot(rnorm(input$inputTest))
    })

    #
    # Render messages
    #
    output$msg <- renderText({
      rVal$msg
    })

    #
    # Render results
    #
    output$result <- renderTable({
      print(rVal$result)
      rVal$result
    })

    #
    # Start the process
    #
    observeEvent(input$start, {
      if (!is.null(rVal$process))
        return()
      rVal$result <- dfEmpty
      rVal$process <- mcparallel({
        analyze()
      })

      rVal$msg <- sprintf("%1$s started", rVal$process$pid)

    })


    #
    # Stop the process
    #
    observeEvent(input$stop, {
      rVal$result <- dfEmpty
      if (!is.null(rVal$process)) {
        tools::pskill(rVal$process$pid)
        rVal$msg <- sprintf("%1$s killed", rVal$process$pid)
        rVal$process <- NULL

        if (!is.null(rVal$obs)) {
          rVal$obs$destroy()
        }
      }
    })

    #
    # Handle process event
    #
    observeEvent(rVal$process, {
      rVal$obs <- observe({
        invalidateLater(500, session)
        isolate({
        result <- mccollect(rVal$process, wait = FALSE)
        if (!is.null(result)) {
          rVal$result <- result
          rVal$obs$destroy()
          rVal$process <- NULL
        }
      })
      })
    })
  }
  )

编辑

也可以看看 :
  • shiny-discuss : child process
  • asynchronous-command-dispatch-in-interactive-r
  • 关于r - 是否可以停止在 Shiny 的内部执行 R 代码(不停止 Shiny 的进程)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30587883/

    相关文章:

    删除除最后一个实例之外的所有重复项

    r - 在 R 中加入参差不齐的数组

    r - 我应该如何创建一个 "clear"按钮来消除 R Shiny 的行?

    r - sf 行之间点的距离

    在 R 中重复表达式几次

    r - Googleway R 替代路线

    sql - 从 R 连接到 Azure 数据库

    R Shiny 使用 iframe 本地文件

    R Leaflet (CRAN) - 如何注册点击标记

    r - R 中的调试选项