停止goroutine中的所有递归函数

7lrncoxx  于 2023-05-04  发布在  Go
关注(0)|答案(4)|浏览(135)

对于一个运行递归函数的goroutine,我想发送一个信号来停止这些递归函数。这是函数(功能并不重要):

func RecursiveFunc(x int, depth int, quit chan bool) int {

    if depth == 0 {
        return 1
    }

    if quit != nil {
        select {
        case <-quit:
            return 0
        default:
        }
    }

    total := 0

    for i := 0; i < x; i++ {

        y := RecursiveFunc(x, depth - 1, quit)

        if y > 0 {
            total += y
        }

    }

    return total
}

这个函数可能需要很长时间才能完成,我想在发送退出信号后停止它并使用结果(无论它是什么)。要运行它,请执行以下操作:

import (
    "fmt"
    "time"
    "sync"
)

func main() {

    quit := make(chan bool)
    wg := &sync.WaitGroup{}
    result := -1

    go func() {
        defer wg.Done()
        wg.Add(1)
        result = RecursiveFunc(5, 20, quit)
    }()

    time.Sleep(10 * time.Millisecond)

    close(quit) // Using `quit <- true` doesn't work

    wg.Wait()

    fmt.Println(result)
}

为了停止goroutine,我使用了一个通道quit,关闭它后,程序运行良好,但是我不想真的关闭通道,我只想发送一个信号quit <- true。但是,quit <- true不起作用,我可能只退出了一个递归示例。
如何通过发送退出信号来停止递归函数的所有示例?

plupiseo

plupiseo1#

你可以使用context来完成你要做的事情。
你可以从外部将一个context.Context对象作为第一个参数传递给你需要停止的函数,并调用相应的cancel函数向该函数发送一个“取消信号”,这将导致context.ContextDone()通道被关闭,被调用的函数将在select语句中被通知取消信号。
下面是该函数如何使用context.Context处理消除信号:

func RecursiveFunc(ctx context.Context, x int, depth int) int {

    if depth == 0 {
        return 1
    }

    select {
    case <-ctx.Done():
        return 0
    default:
    }

    total := 0

    for i := 0; i < x; i++ {

        y := RecursiveFunc(ctx, x, depth-1)

        if y > 0 {
            total += y
        }

    }

    return total
}

下面是如何使用新签名调用函数:

func main() {

    wg := &sync.WaitGroup{}
    result := -1

    ctx, cancel := context.WithCancel(context.Background())

    go func() {
        defer wg.Done()
        wg.Add(1)
        result = RecursiveFunc(ctx, 5, 20)
    }()

    time.Sleep(10 * time.Millisecond)

    cancel()

    wg.Wait()

    fmt.Println(result)
}
ff29svar

ff29svar2#

我最近遇到了类似的情况,就像你的情况一样,退出信号被一个递归分支消耗掉了,其他分支没有信号。我通过在从函数返回之前将停止信号转发到通道来解决这个问题。
例如,可以将递归函数中的select修改为:

if quit != nil {
    select {
    case <-quit:
        quit <- true // forward the signal
        return 0
    default:
    }
}
3mpgtkmj

3mpgtkmj3#

函数递归无限循环,直到条件〉= 10匹配,不要忘记关闭通道并返回

func main() {
    x := 1
    xChan := make(chan int)
    go recursion(x, xChan)
    select {
    case result := <-xChan:
        log.Println("get chan result :", result)
        break
    }
}

func recursion(i int, xChan chan int) {
    if i >= 10 {
        xChan <- i
        close(xChan)
        return
    }
    a := i + i
    log.Println("a :", a)
    recursion(a, xChan)
}
hsgswve4

hsgswve44#

尝试添加标志以继续执行,但它可能不是线程安全的。

var finishIt bool

func RecursiveFunc(x int, depth int, quit chan bool) int {
   if finishIt {
    return 0
   }
//other code here
}

//some code here, but than we decide to stop it
finishIt = true

相关问题