doudou7361 2019-09-25 03:33
浏览 258

ctx超时时,如何完全终止正在运行的go func()?

When I want ctx timeout, what should I do to completely terminate the method that is executing longRunningCalculation()?

package main

import (
    "context"
    "log"
    "time"
)

func longRunningCalculation(timeCost int) chan string {
    result := make(chan string)
    go func() {
        time.Sleep(time.Second * (time.Duration(timeCost)))
        log.Println("Still doing other things...") //Even if it times out, this goroutine is still doing other tasks.
        result <- "Done"
        log.Println(timeCost)
    }()
    return result
}
func jobWithTimeout() {
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()
    select {
    case <-ctx.Done():
        log.Println(ctx.Err())
        return
    case result := <-longRunningCalculation(3):
        log.Println(result)
    }
}

func main() {
    jobWithTimeout()
    time.Sleep(time.Second * 5)
}

What did you expect to see? 2019/09/25 11:00:16 context deadline exceeded

What did you see instead? 2019/09/25 11:00:16 context deadline exceeded 2019/09/25 11:00:17 Still doing other things...

  • 写回答

1条回答 默认 最新

  • duanhongyi2964 2019-09-25 03:50
    关注

    To stop the goroutine started by longRunningCalculation when the caller's context times out, you need to pass ctx into longRunningCalculation and explicitly handle the context timing out, the same way you do in jobWithTimeout

    Doing things that way also means instead of calling time.Sleep, that time.Tick will be a better choice, so both timers are running at the same time. Like so:

    package main
    
    import (
        "context"
        "log"
        "time"
    )
    
    func longRunningCalculation(ctx context.Context, timeCost int) chan string {
        result := make(chan string)
        go func() {
            calcDone := time.Tick(time.Second * time.Duration(timeCost))
            log.Printf("entering select (longRunningCalculation)")
            select {
            case <-ctx.Done():
                result <- "Caller timed out"
                return
            case <-calcDone:
                log.Println("Still doing other things...") //Even if it times out, this goroutine is still doing other tasks.
                result <- "Done"
            }
            log.Println(timeCost)
        }()
        return result
    }
    
    func jobWithTimeout() {
        ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
        defer cancel()
        result := longRunningCalculation(ctx, 3)
        log.Printf("entering select (jobWithTimeout)")
        select {
        case <-ctx.Done():
            log.Println(ctx.Err())
            return
        case res := <-result:
            log.Println(res)
        }
    }
    
    func main() {
        jobWithTimeout()
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥20 蓝牙耳机怎么查看日志
  • ¥15 R语言 拟时序分析降维图如何减少分支
  • ¥15 Fluent齿轮搅油
  • ¥15 八爪鱼爬数据为什么自己停了
  • ¥15 交替优化波束形成和ris反射角使保密速率最大化
  • ¥15 树莓派与pix飞控通信
  • ¥15 自动转发微信群信息到另外一个微信群
  • ¥15 outlook无法配置成功
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统