如何停止goroutine [英] How to stop goroutine

查看:113
本文介绍了如何停止goroutine的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个goroutine调用一个函数,并且有一个特殊的参数,我想要启动或停止这个goroutine。我的问题是这段代码永远不会停止我的goroutine,它每创建一项新工作都会创建。

  quit:= make(chan bool)
run:= make(chan bool)

go func(){
for {
select {
case< -quit:
close(run)
case< -run:$ b $如果x == true {
quit< - b myFunc(c)
default:
}
}
}()

true
} else {
run< - true
}

我如何停止我的日常工作?

解决方案

这个问题有两个部分。

首先,我们需要以某种方式停止子例程,即使父例程停止,它的所有子程序都应该得到通知并停止 - 停止信号的层次结构但没有。



另一方面,父母需要等待它的孩子,直到他们完成。否则,我们会从goroutine返回,甚至在某些goroutine正常完成之前退出应用程序。



为简单起见,我们忽略实现错误处理,超时等。 p>

为了处理第一个问题,我们使用 context.Context ,它给了我们一个很好的执行上下文处理工具和解决方案第二个问题是我们使用 sync.WaitGroup ,这允许我们等待一组goroutines来完成他们的任务。一个简单的示例是:
$ b $ pre $ func main(){
all:=& sync.WaitGroup {}
rootCtx,rootCancel:= context.WithCancel(context.Background())

all.Add(1)
go level1(rootCtx,全部)

//只是为了模拟停止,我们可以使用os信号来代替
// app在3秒后结束
去func(){
time.Sleep(time.Second * 3)
rootCancel()
}()

all.Wait()
}

func level1(parent context.Context,all * sync .WaitGroup){
defer all.Done()
l1Ctx,l1Cancel:= context.WithCancel(parent)
defer l1Cancel()

for i:= 0 ;我< 3; i ++ {
all.Add(1)
去等级2(l1Ctx,全部)
}

用于{
选择{
case< ; -parent.Done():
返回
//其他情况下,如果有的话,
//这是一个样例
case< -time.After(time.Second) :
log.Println(`level1`)
}
}
}
$ b func level2(parent context.Context,all * sync.WaitGroup) {
defer all.Done()
for {
select {
case< -parent.Done():
return
case< - time.After(time.Second):
log.Println(`level2`)
}
}
}

这给了我们一些输出:

  [info] level2 
[info] level2
[info] level2
[info] level1
[info] level2
[info] level1
[info] level2
[info] level2

目前是不提供结合 context.Context sync.WaitGroup 的功能的官方软件包。最近的是 errgroup ,它可以通过一些黑客来类似这个功能。


I have a goroutine that calls a function and with a special parameter i want to start or stop this goroutine. My problem is that this code never stops my goroutine, it creates everytime a new job.

quit := make(chan bool)
run := make(chan bool)

    go func() {
        for {
            select {
            case <-quit:
                close(run)
            case <-run:
                myFunc(c)
            default:
            }
        }
    }()

    if x == true {
        quit <- true
    } else {
        run <- true
    }

How do I stop my routine?

解决方案

This problem has two parts.

First we need to stop child goroutines somehow in a way that even if a parent goroutines stops, all it's children should get notified and stop - a hierarchy of stop signals that goes down but not up.

On the other hand the parent needs to wait for it's children until they are done. Otherwise we would return from a goroutine or even exit from the app before some goroutines are finished properly.

For simplicity we ignore implementing error handling, timeouts and the like.

For handling the first problem we use context.Context which gives us a nice hierarchy of execution context handling tools and for solving the second problem we use sync.WaitGroup which allows us to wait for a group of goroutines to complete their tasks. A simple demonstration would be:

func main() {
    all := &sync.WaitGroup{}
    rootCtx, rootCancel := context.WithCancel(context.Background())

    all.Add(1)
    go level1(rootCtx, all)

    // just to simulate stop, we could use an os signal instead
    // app ends after 3 seconds
    go func() {
        time.Sleep(time.Second * 3)
        rootCancel()
    }()

    all.Wait()
}

func level1(parent context.Context, all *sync.WaitGroup) {
    defer all.Done()
    l1Ctx, l1Cancel := context.WithCancel(parent)
    defer l1Cancel()

    for i := 0; i < 3; i++ {
        all.Add(1)
        go level2(l1Ctx, all)
    }

    for {
        select {
        case <-parent.Done():
            return
        // other cases if any,
        // this is a sample
        case <-time.After(time.Second):
            log.Println(`level1`)
        }
    }
}

func level2(parent context.Context, all *sync.WaitGroup) {
    defer all.Done()
    for {
        select {
        case <-parent.Done():
            return
        case <-time.After(time.Second):
            log.Println(`level2`)
        }
    }
}

Which gives us some output like:

[  info ] level2
[  info ] level2
[  info ] level2
[  info ] level1
[  info ] level2
[  info ] level1
[  info ] level2
[  info ] level2

Currently there is no official package that provide a functionality which combines context.Context and sync.WaitGroup. The nearest thing is an errgroup which can resemble this functionality with some hacks.

这篇关于如何停止goroutine的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆