如何终止一个正在进行的协程?

2021-08-30 15:17:45 +08:00
 777777

利用 context.WithCancel()来终止协程,但存在一个问题:cancel()执行后,必须等 for 循环执行完毕 goroutine 才退出。

for {
  select {
    case <-Ctx.Done():
      return
    default:
      for i := 0; i < 100; i++ {
        // 业务逻辑
      }
  }
}

需求为:cancel()后协程立马退出不再执行后面的循环。
目前我的解决方法:单独起一个协程用来监听退出信号,然后通过全局变量通知业务逻辑循环退出。

flag := false
go func() {
  for {
    select {
      case <-Ctx.Done():
        flag = true
        return
  }
}()

for i:=0; i < 100; i++ {
  if flag {
    return
  }
  // 业务逻辑
}

请问最佳实践应该是如何退出?

3756 次点击
所在节点    Go 编程语言
21 条回复
dream10201
2021-08-30 15:24:09 +08:00
瞎想的,你把 select case 放到 for 循环里面不行?
dream10201
2021-08-30 15:25:34 +08:00
for {
for i := 0; i < 100; i++ {
select {
case <-Ctx.Done():
return
default:
// 业务逻辑
}
}
}
rimutuyuan
2021-08-30 15:26:40 +08:00
```
for {
for i := 0; i < 100; i++ {
select {
case <-Ctx.Done():
return
default:
// 业务逻辑
}
}
}```
BBCCBB
2021-08-30 15:26:59 +08:00
这种可以在 for 里每次检测 ctx.Done()... 不过不是最佳实践.
和你图中这个方法差不多,, 不过不知道你图中这个方法有没有变量可见性的问题? 导致 flag=true 后在当前协程并不可见?
777777
2021-08-30 15:50:04 +08:00
@BBCCBB 是可见的
777777
2021-08-30 15:52:49 +08:00
@dream10201 这样有问题吧,如果不调用 cancel(),最外面 for 循环不会退出。
sadfQED2
2021-08-30 16:06:43 +08:00
这个问题我在 java 里面也研究过,最后结果就是无解,只能业务代码里面每次循环都判断
xx6412223
2021-08-30 16:13:13 +08:00
直接退出就不是合理的设计。
caryqy
2021-08-30 16:24:47 +08:00
执行前检查 Done,

执行后提交前再次检查 Done,根据结果来收尾。

考虑的粒度即使再细都会碰到 执行中取消 这个问题,所以到某个程度之后就 禁止用户取消
haochen2
2021-08-30 17:11:31 +08:00
如果业务逻辑超时运行或着阻塞,根本走不到 ctx.Done 那个 case 的地方
cpstar
2021-08-30 17:34:57 +08:00
循环第二位置用 i<100&&ctx.done() 不好么?还非得一个 switch-case ?
至于楼上说的业务阻塞,那就得放到业务里边继续判断了。

多线程运转,直接干掉线程,哈
MidGap
2021-08-30 17:46:36 +08:00
runtime.Goexit()
fpure
2021-08-30 18:17:32 +08:00
@sadfQED2 Java 里面哪有什么协程?
sadfQED2
2021-08-30 18:17:50 +08:00
@fpure java 线程
s4nd
2021-08-30 18:57:42 +08:00
老哥,你这头像是认真的吗,nft 大佬
MineDog
2021-08-30 20:19:39 +08:00
@sadfQED2 #7 java 怎么会无解呢,java 一般就是 Interrupted+状态判断啊
cheng6563
2021-08-31 09:15:33 +08:00
@sadfQED2 Java 一顿 Interrupt 就行了,只不过没人管 InterruptedException 倒是真的
codeface
2021-08-31 13:05:14 +08:00
caoyouming
2021-09-01 12:09:53 +08:00
你这里的 c 表示的是什么呀?
ltf127001
2021-09-01 17:55:42 +08:00
@caoyouming 根据我在菜鸟教程学了两天 go 的经验,这个应该是个通道( channel )

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/798857

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX