【问题标题】:How to stop goroutine from client?如何从客户端停止 goroutine?
【发布时间】:2016-08-01 14:29:14
【问题描述】:

我需要创建一个 html 页面,它有两个按钮,一个将启动一个 goroutine,它有一个无限循环,另一个按钮需要打破无限循环。根据我的阅读,我了解到不能从外部杀死一个 goroutine。有没有办法实现这个?我的代码如下:

command := c.GetString("command") // from client to determine which button is clicked
quit := make(chan bool)
switch command {
    case "start":    // Button to start goroutine
        go func() {
            i := 0
            for {
                select {
                    case <- quit:
                        return
                     default:
                         fmt.Println("i: ", i)
                         i++
                         time.Sleep(3000 * time.Millisecond)
                 }
             }
         }()
     case "stop":    // Button to stop goroutine
         quit <- true
}

【问题讨论】:

  • 这几乎是标准的做法,是的,你有什么具体问题吗?
  • 是否允许多次按“开始”按钮,即可能有多个goroutine在运行?
  • @ain 不,不会有多个 goroutines...
  • @Jsor 停止不起作用。即使按下停止按钮,循环仍在继续..
  • 无关,在你的“停止”情况下关闭退出(close(quit))就像通过它发送消息一样容易,并且关闭不会阻塞(虽然它 如果您尝试多次这样做,将会恐慌)。我通常使用 close,因为它可以在单个操作中终止多个侦听例程,而不必向每个例程发送消息。

标签: go goroutine


【解决方案1】:

您对设计的看法已经正确。一个问题是您每次收到命令时都在创建新频道。这意味着无法与之前启动的 goroutine 进行通信。您需要有一个quit 通道,该通道保持在请求之间的范围内。试试下面的方法(未经测试):

func listenForCommand() {
    var quit chan bool

    for {
        // command receiver, should fire for each command received
        command := c.GetString("command")

        switch command {
        case "start":
            if quit != nil {
                continue
            }
            quit = make(chan bool)
            go func() {
                i := 0
                for {
                    select {
                    case <-quit:
                        return
                    default:
                        fmt.Println("i: ", i)
                        i++
                        time.Sleep(3000 * time.Millisecond)
                    }
                }
            }()
        case "stop":
            if quit == nil {
                continue
            }
            quit <- true
            close(quit)
            quit = nil
        }
    }
}

您现在可以拨打listenForCommand() 开始监听命令。此示例假定有另一个进程填充c,因此c.GetString("command") 在可用时返回命令,或者阻塞并等待命令到达。

【讨论】:

  • 您能否解释一下从您的命令接收器循环/回调中定义的注释?我测试了您的代码,但停止不起作用。可能是我又把频道定义错了。
  • 已在上面编辑。请注意,它仍然是一个示例。为了让上面的例子正常工作,c.GetString("command") 需要像一个频道一样,如上所述。
  • 我们不能跳出循环吗?我认为在这段代码中,开关控制从案例“开始”转移到案例“停止”,循环仍在运行。
  • 你是如何定义c.GetString的?而c? 类型
  • type c是控制器接收器,c.GetString是beego函数。
猜你喜欢
  • 2013-12-06
  • 2018-08-14
  • 1970-01-01
  • 2011-10-12
  • 2017-07-19
  • 2018-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多