背景是这样的:
用户在页面点击一个执行,这时候会有一个 goroutine job 在 running 中,
那么用户再次点击停止执行,这次请求如何去关闭上次正在运行的 goroutine ?

背景是这样的:
用户在页面点击一个执行,这时候会有一个 goroutine job 在 running 中,
那么用户再次点击停止执行,这次请求如何去关闭上次正在运行的 goroutine ?
1 Sendya Sep 28, 2022 via Android 创建 job 的时候弄个 context.WithCancal ,在需要的时候调用 cancel 取消掉即可 |
2 caicaiwoshishui OP @Sendya 这是 2 次不同请求,第二次请求怎么拿到第一次的 goroutine ,goroutine 对象能保存嘛 |
3 MoYi123 Sep 28, 2022 用 context.WithCancal 还有看 job 是什么类型的, 如果是纯 cpu 计算的, 你要在每几次循环里面确认是否要退出, 如果是等待网络 io 之类的,需要 select <- ctx.Done() 总之没有那种不侵入代码的写法. |
4 14v45mJPBYJW8dT7 Sep 28, 2022 可以用{jobid: cancelFunc}的格式保存,需要结束时获取 cancelFunc 执行一下就行了 |
5 plutome Sep 28, 2022 @rimutuyuan 楼上正解, 注意下 map 的并发安全问题,以及锁,还有就是加一个定时清理机制就可以解决需求了. |
6 Maboroshii Sep 28, 2022 via Android go 不提供这个,需要自己在逻辑里面检测是否需要退出。context 的原理就是传一个 chan 给函数里面,函数自己判断 cancel 是否被调用。 |
7 paccco Sep 28, 2022 没有办法直接关闭指定的 goroutine ,可以采用曲线救国的方式,在你 goroutine 的业务中做特殊处理通知让其自行结束 |
8 caicaiwoshishui OP @rimutuyuan 感谢 确实是个好思路 |
9 caicaiwoshishui OP @Maboroshii 谢谢,主要是 2 次请求是不同的 context ,第二次请求如何拿到第一次的 context |
10 bruce0 Sep 28, 2022 @caicaiwoshishui 像楼上说的那样, 用个全局 map 保存一下(记得加锁), 第一次开始 goroutine 的时候写到 cookie 里一个 key,第二次通过 cookie 里的 key 查询 map, 能找到 就取消掉 |
11 dzdh Sep 28, 2022 生成 jobid 传给前端。点击取消时把 jobid 传回来 或者 redis 或其他存储 点击任务(必定有个 id),redis.set(id, running) 。协程中再开个协程查 redis.get(id)不等于 running 退出 |
12 dzdh Sep 28, 2022 每次点击 if redis.get(id) == running ; redis.set(id,quit) else go func(){redis.set(id,running) |
13 lanlanye Sep 28, 2022 就是 web 开发中的 session 解决的问题,无非是把 context 存在里面罢了 |
14 frank1256 Sep 28, 2022 @caicaiwoshishui context 持久化就行了,放 redis 之类的缓存中间件就行了 |
15 useben Sep 28, 2022 盲猜是任务管理列表 |
17 dzdh Sep 29, 2022 @777777 #16 有一种情况 拿 ffmpeg 转换视频来说。可能是这样的 go func(ctx, video-source) { for { select { <ctx.done; 在哪一步启动 ffmpeg 呢 |
18 guanhui07 Sep 30, 2022 ```golang func main() { ch := make(chan struct{}) ctx, cancel := context.WithCancel(context.Background()) go func(ctx context.Context) { for { select { case <-ctx.Done(): ch <- struct{}{} return default: fmt.Println("test11111...") } time.Sleep(500 * time.Millisecond) } }(ctx) go func() { time.Sleep(3 * time.Second) cancel() }()br /> <-ch fmt.Println("结束") } ``` 是这样吗 |
19 caicaiwoshishui OP @777777 目前是按 11 楼的做法 |
20 caicaiwoshishui OP @777777 但是要结合 ctx cancel ,不然一个 job 如果有多个逻辑,比如 job 里面有执行 a,b,c 三个逻辑块,那么需要把三个逻辑都封装成函数,并且传入 ctx ;当执行第一个逻辑块 a 的时候,收到 ctx cancel ,这个 job 就会退出,并且不会往下执行 |