dpql57753 2018-04-03 09:16
浏览 186
已采纳

App Engine Go:如何终止正在运行的goroutine

I want to run 2 goroutines parallel in App Engine, so that when the first goroutine finish its job, the handler doesn't need to wait the second goroutine - it stops the secend goroutine and returns the result to the client. Is this possible? I tried it with context.WithCancel(), but it didn't work (I use go1.6).

Here is my code:

package mytest

import (
    "net/http"
    "sync"
    "time"

    "golang.org/x/net/context"
    "google.golang.org/appengine"
    "google.golang.org/appengine/log"
    "google.golang.org/appengine/urlfetch"
)

func init() {
    http.HandleFunc("/test", handlerTest)
    http.HandleFunc("/testwait10s", handlerTest10s)
    http.HandleFunc("/testwait5s", handlerTest5s)
}

func handlerTest(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    ctx, _ := context.WithTimeout(c, 30*time.Second)

    ctx1, ctx1Cancel := context.WithCancel(ctx)
    ctx2, ctx2Cancel := context.WithCancel(ctx)

    var wg sync.WaitGroup
    wg.Add(2)

    go func() {
        defer wg.Done()
        log.Infof(ctx1, "Go1 begin ...")
        client1 := urlfetch.Client(ctx1)
        _, err := client1.Get("http://APP_NAME.appspot.com/testwait5s")
        if err != nil {
            log.Errorf(ctx1, "Go1 failed:  %v", err)
        }
        ctx2Cancel()
        log.Infof(ctx1, "Go1 over ...")
    }()

    go func() {
        defer wg.Done()
        log.Infof(ctx2, "Go2 begin ...")
        client2 := urlfetch.Client(ctx2)
        _, err := client2.Get("http://APP_NAME.appspot.com/testwait10s")
        if err != nil {
            log.Errorf(ctx2, "Go2 failed %v", err)
        }
        ctx1Cancel()
        log.Infof(ctx2, "Go2 over ...")
    }()

    wg.Wait()
    log.Infof(ctx1, "Go1 and GO2 over")
}

func handlerTest10s(w http.ResponseWriter, r *http.Request) {
    time.Sleep(10 * time.Second)
    return
}

func handlerTest5s(w http.ResponseWriter, r *http.Request) {
    time.Sleep(5 * time.Second)
    return
}

Any ideas? Thanks!

  • 写回答

2条回答 默认 最新

  • dre93205 2018-04-03 12:10
    关注

    Just create a notification channel and send there a signal that one of computations is over and you can proceed without waiting for the other.

    func handlerTest(w http.ResponseWriter, r *http.Request) {
        c := appengine.NewContext(r)
        ctx, cancel := context.WithTimeout(c, 30*time.Second)
        done := make(chan error, 2)
    
        work := func(url, name string) {
            log.Infof(ctx, "%s begin ...", name)
            client := urlfetch.Client(ctx)
            req, err := http.NewRequest(http.MethodGet, url, nil)
            if err != nil {
                log.Errorf(ctx, "%s failed:  %v", name, err)
                done <- err
                return
            }
            req = req.WithContext(ctx)
            _, err = client.Do(req)
            done <- err
            if err != nil {
                log.Errorf(ctx, "%s failed:  %v", name, err)
                return
            }
            cancel()
            log.Infof(ctx, "%s over ...", name)
        }
        go work("go1", "http://APP_NAME.appspot.com/testwait5s")
        go work("go2", "http://APP_NAME.appspot.com/testwait10s")
    
        for i := 0; i < cap(done); i++ {
            if err := <-done; err == nil {
                log.Infof(ctx, "executed without errors")
                return
            }
        }
        log.Error(ctx, "both computations have failed")
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 运筹学排序问题中的在线排序
  • ¥15 关于docker部署flink集成hadoop的yarn,请教个问题 flink启动yarn-session.sh连不上hadoop,这个整了好几天一直不行,求帮忙看一下怎么解决
  • ¥30 求一段fortran代码用IVF编译运行的结果
  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 lammps拉伸应力应变曲线分析
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥15 请问Lammps做复合材料拉伸模拟,应力应变曲线问题