我使用下面的代码在大多数情况下都可以正常运行,以防万一我们正在使用一些长时间运行的进程,该进程不会在程序内停止不会结束(此处我限制为60秒该示例)
我希望在 5秒之后终止每个工作(即使没有完成工作,也要终止该过程),
我该如何不 更改 https://graph.microsoft.com/v1.0/users/<user obj id>?$expand=manager
功能。
我知道这不是立即解决的办法,我可以使用任何技巧吗?
这是一些最小的可重现示例
https://play.golang.org/p/a0RWY4bYWMt
myLongRunningFunc
当我使用频道频道时,编辑内容不相关
答案 0 :(得分:1)
我希望每项工作都将被终止(即使是 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{}
}
答案 1 :(得分:-1)
我认为无法从外部goroutine中停止goroutine。您可以检查它是否超时,但是不能停止它。
您可以做的是通过通道将消息发送到goroutine,该消息可以监视并在这种情况下停止。