为了账号安全,请及时绑定邮箱和手机立即绑定

有没有办法停止长时间阻塞功能?

有没有办法停止长时间阻塞功能?

Go
互换的青春 2021-07-07 13:04:01
我有一个运行几分钟的函数,我正在尝试找到一种方法来使用通道停止它。我想我不能像在下面的代码中那样做,因为我认为它select只会stop在default完成后处理这种情况。package mainimport (    "fmt"    "time")func main() {    stop := make(chan int)    go func() {        for {            select {            case <-stop:                fmt.Println("return")                return            default:                fmt.Println("block")                time.Sleep(5 * time.Second) // simulate a long running function                fmt.Println("unblock")            }        }    }()    time.Sleep(1 * time.Second)    stop <- 1}
查看完整描述

3 回答

?
繁华开满天机

TA贡献1816条经验 获得超4个赞

我认为你做不到:从某种意义上说,Go 中的 goroutine 是合作的:直到一个 goroutine主动尝试以某种方式确定它是否应该退出,否则没有办法强迫它这样做。

我会说它实际上是一个特性,因为如果你可以强行获取一个长时间运行的 goroutine,你将无法确保它干净地退出,即正确释放它获得的所有资源。

因此,要么接受这个(例如,如果您的进程想要退出,只需等待该 goroutine 完成)或对其进行重构,以便它定期检查是否发出退出信号。或者甚至考虑将它执行的任务卸载到外部进程(但请注意,虽然终止进程以释放它从操作系统获取的资源是安全的,但对于进程可能已经更新的外部数据而言是不安全的——如文件)。


查看完整回答
反对 回复 2021-07-12
?
富国沪深

TA贡献1790条经验 获得超9个赞

如果您以某种方式使您的功能可中断,您只能这样做,即您无法自行停止阻塞调用。如果您自己编写阻塞函数,您通常可以使用多个案例和通道来设计一个选择。


你的例子看起来像


package main


import (

    "fmt"

    "time"

)


func main() {

    stop := make(chan int)


    go func() {

        for {

            fmt.Println("block")

            select {

            case <-time.After(5 * time.Second):

                fmt.Println("unblock")

            case <-stop:

                fmt.Println("stopped")

                return

            }


        }

    }()


    time.Sleep(2 * time.Second)

    stop <- 1


    // this is just to give the goroutine time to write "stopped" before we exit

    select{}

}


查看完整回答
反对 回复 2021-07-12
  • 3 回答
  • 0 关注
  • 207 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信