【问题标题】:How to signal to a goroutine to stop running?如何向 goroutine 发出信号以停止运行?
【发布时间】:2014-11-25 03:42:55
【问题描述】:

我正在尝试停止执行例行程序,但找不到实现此目的的方法。我正在考虑使用第二个频道,但如果我从中读取它会阻止它不是吗?这是一些我希望能解释我想要做什么的代码。

package main

import "fmt"
import "time"

func main() {

    var tooLate bool

    proCh := make(chan string)

    go func() {
        for {
               fmt.Println("working")
        //if is tooLate we stop/return it
            if tooLate { 
            fmt.Println("stopped")
                return
            }
       //processing some data and send the result on proCh
            time.Sleep(2 * time.Second)
            proCh <- "processed"
            fmt.Println("done here")

        }
    }()
    select {
    case proc := <-proCh:
        fmt.Println(proc)
    case <-time.After(1 * time.Second):
        // somehow send tooLate <- true
        //so that we can stop the go routine running
        fmt.Println("too late")
    }

    time.Sleep(4 * time.Second)
    fmt.Println("finish\n")
}

Play this thing

【问题讨论】:

标签: go


【解决方案1】:

实现这一点的方法很少,最简单、最方便的是使用另一个渠道,例如:

func main() {
    tooLate := make(chan struct{})
    proCh := make(chan string)

    go func() {
        for {
            fmt.Println("working")
            time.Sleep(1 * time.Second)
            select {
            case <-tooLate:
                fmt.Println("stopped")
                return
            case proCh <- "processed": //this why it won't block the goroutine if the timer expirerd.
            default: // adding default will make it not block
            }
            fmt.Println("done here")

        }
    }()
    select {
    case proc := <-proCh:
        fmt.Println(proc)
    case <-time.After(1 * time.Second):
        fmt.Println("too late")
        close(tooLate)
    }

    time.Sleep(4 * time.Second)
    fmt.Println("finish\n")
}

playground

您也可以考虑使用sync.Cond

【讨论】:

  • 为什么我们需要 case proCh &lt;- "processed": 在第一个 go 例程的第二个选择案例中?如果计时器到期tooLate &lt;- true,它将返回,所以不可能有这种情况不是吗?
  • @AnthonyHat 不,因为在 case &lt;-time.After(1 * time.Second) 之后,你的 goroutine 会在尝试 proCh &lt;- "processed" 时卡住,并且在程序退出之前它永远不会解除阻塞。
  • @OneOfOne 如果计时器到期,goroutine 只会返回 case &lt;-tooLate: fmt.Println("stopped") return 它似乎没有阻塞,我也没有看到任何原因。 play.golang.org/p/MvmjBXfAqV
  • @AnthonyHat default: 在 select 中使它成为非阻塞的,当你评论 close(tooLate) 时你做到了,所以 case &lt;-tooLate 永远不会选择。
  • 为什么要把chan类型设为Struct{}?
猜你喜欢
  • 2018-08-13
  • 2020-04-08
  • 1970-01-01
  • 2021-07-27
  • 1970-01-01
  • 2019-04-15
  • 1970-01-01
  • 1970-01-01
  • 2021-07-04
相关资源
最近更新 更多