亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Goroutine-停止運行進程

Goroutine-停止運行進程

Go
慕碼人8056858 2022-07-11 15:56:58
我使用以下代碼在大多數情況下都可以正常工作,以防我們使用一些長時間運行的進程,它不會在程序內部停止并不會結束(這里我限制為 60 秒的示例)我希望每項工作在5 秒后終止(即使沒有完成工作也終止進程),我怎樣才能在 不 改變功能的情況下做到這一點myLongRunningFunc。我知道這不是直接解決它,我可以使用任何技巧嗎?這是一些最小的可重現示例https://play.golang.org/p/a0RWY4bYWMtpackage mainimport (    "context"    "errors"    "fmt"    "time"    "github.com/gammazero/workerpool")func main() {    // here define a timeout for 5 sec,    // the task should be terminate after 5 sec    ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)    defer cancel()    runner := newRunner(ctx, 10)    runner.do(job{        Name: "a",        Task: func() jobResult {            select {            case <-ctx.Done():                return jobResult{Error: errors.New("Timedout, exiting")}            default:                myLongRunningFunc("A job")            }            return jobResult{Data: "from a"}        },    })    runner.do(job{        Name: "b",        Task: func() jobResult {            select {            case <-ctx.Done():                return jobResult{Error: errors.New("Timeouts, exiting")}            default:                myLongRunningFunc("B job")            }            return jobResult{Data: "from b"}        },    })    results := runner.getjobResults()    fmt.Println(results)    time.Sleep(time.Second * 60)}func myLongRunningFunc(name string) {    for i := 0; i < 100000; i++ {        time.Sleep(time.Second * 1)        msg := "job" + name + " running..\n"        fmt.Println(msg)    }}type runner struct {    *workerpool.WorkerPool    ctx     context.Context    kill    chan struct{}    result  chan jobResult    results []jobResult}func (r *runner) processResults() {    for {        select {        case res, ok := <-r.result:            if !ok {                goto Done            }            r.results = append(r.results, res)        }    }Done:    <-r.kill}當我使用圣壇頻道時,編輯不相關
查看完整描述

2 回答

?
慕少森

TA貢獻2019條經驗 獲得超9個贊

我希望每個作業在 5 秒后終止(即使它沒有完成工作也終止進程),我怎樣才能在不更改函數 myLongRunningFunc 的情況下做到這一點。


然后你只需添加一個 5 秒的服務員然后退出。


package main


import (

    "context"

    "errors"

    "fmt"

    "time"


    "github.com/gammazero/workerpool"

)


func main() {

    go func() {

        // here define a timeout for 5 sec,

        // the task should be terminate after 5 sec

        ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)

        defer cancel()


        runner := newRunner(ctx, 10)


        runner.do(job{

            Name: "a",

            Task: func() jobResult {

                select {

                case <-ctx.Done():

                    return jobResult{Error: errors.New("Timedout, exiting")}

                default:

                    myLongRunningFunc("A job")

                }

                return jobResult{Data: "from a"}

            },

        })


        runner.do(job{

            Name: "b",

            Task: func() jobResult {

                select {

                case <-ctx.Done():

                    return jobResult{Error: errors.New("Timeouts, exiting")}

                default:

                    myLongRunningFunc("B job")

                }


                return jobResult{Data: "from b"}

            },

        })


        results := runner.getjobResults()

        fmt.Println(results)

        time.Sleep(time.Second * 60)

    }()

    <-time.After(time.Second * 5)

}


func myLongRunningFunc(name string) {

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

        time.Sleep(time.Second * 1)

        msg := "job" + name + " running..\n"

        fmt.Println(msg)

    }

}


type runner struct {

    *workerpool.WorkerPool

    ctx     context.Context

    kill    chan struct{}

    result  chan jobResult

    results []jobResult

}


func (r *runner) processResults() {

    for {

        select {

        case res, ok := <-r.result:

            if !ok {

                goto Done

            }

            r.results = append(r.results, res)

        }

    }

Done:

    <-r.kill

}


func newRunner(ctx context.Context, numRunners int) *runner {

    r := &runner{

        WorkerPool: workerpool.New(numRunners),

        ctx:        ctx,

        kill:       make(chan struct{}),

        result:     make(chan jobResult),

    }

    go r.processResults()

    return r

}


func (r *runner) do(j job) {

    r.Submit(r.wrap(&j))

}


func (r *runner) getjobResults() []jobResult {

    r.StopWait()

    close(r.result)

    r.kill <- struct{}{}

    return r.results

}


func (r *runner) wrap(job *job) func() {

    return func() {

        job.result = make(chan jobResult)

        go job.Run()

        select {

        case res := <-job.result:

            r.result <- res

        case <-r.ctx.Done():

            fmt.Printf("Job '%s' should stop here\n", job.Name)

            r.result <- jobResult{name: job.Name, Error: r.ctx.Err()}

        }

    }

}


type job struct {

    Name    string

    Task    func() jobResult

    Context context.Context

    result  chan jobResult

    stopped chan struct{}

    done    context.CancelFunc

}


func (j *job) Run() {

    result := j.Task()

    result.name = j.Name

    j.result <- result

}


type jobResult struct {

    name  string

    Error error

    Data  interface{}

}


查看完整回答
反對 回復 2022-07-11
?
海綿寶寶撒

TA貢獻1809條經驗 獲得超8個贊

我認為不可能從外部 goroutine 中停止 goroutine。您可以檢查它是否超時,但是,您不能停止它。

您可以做的是通過通道向 goroutine 發送消息,在這種情況下可以對其進行監視和停止。

你可以在這里找到例子


查看完整回答
反對 回復 2022-07-11
  • 2 回答
  • 0 關注
  • 197 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號