5

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

 2 years ago
source link: https://www.v2ex.com/t/798857
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

V2EX  ›  Go

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

  777777 · 5 小时 48 分钟前 · 1340 次点击

利用 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
  }
  // 业务逻辑
}

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

第 1 条附言  ·  5 小时 11 分钟前

是这样一个场景:用户创建任务,起一个 goroutine 去执行,执行过程中,用户想要取消这个任务。

第 2 条附言  ·  5 小时 4 分钟前

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

感谢大家的回答,每次循环都检测一次退出信号就好了。
延伸出另一个问题:用户取消任务,如何让default里的业务逻辑立马终止?

第 3 条附言  ·  4 小时 44 分钟前

看了一下os.exec.cmd.Start()的源码

	if c.ctx != nil {
		c.waitDone = make(chan struct{})
		go func() {
			select {
			case <-c.ctx.Done():
				c.Process.Kill()
			case <-c.waitDone:
			}
		}()
	}

另起一个goroutine监听cancel(),然后kill掉执行的process。
类比本问题,一个协程执行任务,一个协程监听任务的cancel(),任务取消直接kill掉执行任务的协程且监听协程也退出。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK