在下面的代码中,如果其中一个启动的go例程花费太长时间(例如> 10秒)来完成,我该如何添加正确的超时错误处理?请注意,我不希望每个例行程序都有一个“整体”超时但是超时,因此我也可以知道在我的错误报告中哪个例行程序超时。
var wg sync.WaitGroup
for _, element:= range elements{
wg.Add(1)
go doWork(element, &wg)
}
wg.Wait()
亲切的问候
答案 0 :(得分:2)
很好的方法是使用context.WithDeadline
:
// WithDeadline returns a copy of the parent context with the deadline adjusted // to be no later than d. If the parent's deadline is already earlier than d, // WithDeadline(parent, d) is semantically equivalent to parent. The returned // context's Done channel is closed when the deadline expires, when the returned // cancel function is called, or when the parent context's Done channel is // closed, whichever happens first. // // Canceling this context releases resources associated with it, so code should // call cancel as soon as the operations running in this Context complete.
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(100*time.Millisecond))
// Even though ctx will be expired, it is good practice to call its
// cancelation function in any case. Failure to do so may keep the
// context and its parent alive longer than necessary.
defer cancel()
select {
case <-time.After(1 * time.Second):
fmt.Println("overslept")
case <-ctx.Done():
fmt.Println(ctx.Err())
}
}
答案 1 :(得分:1)
我确实遇到了同样的问题并提出了这种方法:
https://play.golang.org/p/9F9T_sYIof
使用:c = b.stack().to_frame(a.index[0]).T.reindex(a.index, method='ffill')
print (c)
A B C
3 4 5 3 4 5 3 4 5
2010-01-29 1 1 1 1 1 1 1 1 1
2010-02-26 1 1 1 1 1 1 1 1 1
2010-03-31 1 1 1 1 1 1 1 1 1
2010-04-30 1 1 1 1 1 1 1 1 1
2010-05-31 1 1 1 1 1 1 1 1 1
2010-06-30 1 1 1 1 1 1 1 1 1
2010-07-30 1 1 1 1 1 1 1 1 1
2010-08-31 1 1 1 1 1 1 1 1 1
2010-09-30 1 1 1 1 1 1 1 1 1
2010-10-29 1 1 1 1 1 1 1 1 1
2010-11-30 1 1 1 1 1 1 1 1 1
2010-12-31 1 1 1 1 1 1 1 1 1
d = pd.concat([a,c], axis=1).sort_index(axis=1)
print (d)
A B C
1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
2010-01-29 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1
2010-02-26 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1
2010-03-31 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1
2010-04-30 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1
2010-05-31 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1
2010-06-30 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1
2010-07-30 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1
2010-08-31 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1
2010-09-30 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1
2010-10-29 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1
2010-11-30 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1
2010-12-31 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1
:
https://play.golang.org/p/WK0ebe0c9t
不知道这样做是否正确,但是有效:
context.WithTimeout(context.Background(), 10*time.Second)
注意package main
import (
"context"
"fmt"
"sync"
"time"
)
func doWork(element int, wg *sync.WaitGroup) {
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(10*time.Second))
defer cancel()
ch := make(chan struct{})
go func(ch chan struct{}) {
time.Sleep(time.Second)
fmt.Printf("element = %+v\n", element)
ch <- struct{}{}
}(ch)
select {
case <-ch:
case <-ctx.Done():
fmt.Println(ctx.Err())
}
wg.Done()
}
func main() {
var wg sync.WaitGroup
elements := []int{1, 2, 3}
for _, element := range elements {
wg.Add(1)
go doWork(element, &wg)
}
wg.Wait()
}
函数中的goroutine:
doWork
这是我不知道是否是最佳方式的部分,但似乎是在使用上下文时主要想要处理go func(ch chan struct{}) {
// your code logic goes here
}(ch)
答案 2 :(得分:0)
您可以通过以下方式使用Context:
func doWork(ctx context.Context, element Element, wg &sync.WaitGroup) {
defer wg.Done()
done := make(chan struct{})
go func() {
// do some work on element
done <- struct{}{} // signal work is done
}
select {
case <- done:
{
// work completed in time
}
case <- ctx.Done:
{
// timeout reached
}
}
}
contexts := make([]*context.Context, len(elements))
for _, element:= range elements{
wg.Add(1)
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
contexts = append(contexts, ctx)
go doWork(ctx, element, &wg)
}
wg.Wait()
for i, ctx := range contexts {
if ctx.Err() {
fmt.Println("Go routine ", i, "canceled due to", ctx.Err())
}
}