英文:
Sequence of events leading up to cancellation of context
问题
在下面的程序中,C1
和C2
中都有一个选择序列。在C1
中定义了一个1.5秒的截止时间上下文,超过截止时间后,取消上下文,导致ctx.Done()
,阻止了在C2
中读取整数的操作,进而导致C1
中的ctx.Done()
。
如果是这种情况,那么在上下文已经被取消的情况下,C1
中的cancelCtx()
有什么用处呢?
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx := context.Background()
C1(ctx)
}
func C1(ctx context.Context) {
deadline := time.Now().Add(1500 * time.Millisecond)
ctx, cancelCtx := context.WithDeadline(ctx, deadline)
printCh := make(chan int)
go C2(ctx, printCh)
for num := 1; num <= 3; num++ {
select {
case printCh <- num:
time.Sleep(1 * time.Second)
case <-ctx.Done():
fmt.Printf("C1: Finished\n")
}
}
cancelCtx()
time.Sleep(100 * time.Millisecond)
}
func C2(ctx context.Context, printCh <-chan int) {
for {
select {
case num := <-printCh:
fmt.Printf("C2: %d\n", num)
case <-ctx.Done():
if err := ctx.Err(); err != nil {
fmt.Printf("C2 Error: %s\n", err)
}
fmt.Printf("C2: Finished\n")
return
}
}
}
英文:
In the below program, there is a select sequence in both C1
& C2
. A deadline context for 1.5 seconds is defined in C1
, which after the deadline, cancels the context, leads to ctx.Done()
and prevents the reading of integers in C2
which would further cancel the context and lead to ctx.Done()
in C1
.
If that is the case then what use is cancelCtx()
in C1
when the context is already being cancelled?
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx := context.Background()
C1(ctx)
}
func C1(ctx context.Context) {
deadline := time.Now().Add(1500 * time.Millisecond)
ctx, cancelCtx := context.WithDeadline(ctx, deadline)
printCh := make(chan int)
go C2(ctx, printCh)
for num := 1; num <= 3; num++ {
select {
case printCh <- num:
time.Sleep(1 * time.Second)
case <-ctx.Done():
fmt.Printf("C1: Finished\n")
}
}
cancelCtx()
time.Sleep(100 * time.Millisecond)
}
func C2(ctx context.Context, printCh <-chan int) {
for {
select {
case num := <-printCh:
fmt.Printf("C2: %d\n", num)
case <-ctx.Done():
if err := ctx.Err(); err != nil {
fmt.Printf("C2 Error: %s\n", err)
}
fmt.Printf("C2: Finished\n")
return
}
}
}
答案1
得分: 2
根据context.WithDeadline()
的文档:
取消此上下文会释放与其关联的资源,因此代码应在此上下文中的操作完成后尽快调用cancel。
因此,最佳实践是在不再需要上下文时尽快调用cancelCtx()
(或者您称之为的函数),即使这意味着多次调用也是很常见的(参见这里)。
在您的示例中,这可能有另一个好处。假设截止时间是可配置的,并且已增加到5秒;现在取消上下文会导致通过调用cancelCtx()
触发C2
的终止,而不是等待截止时间(playground)。
英文:
As per the docs for context.WithDeadline()
:
>Canceling this context releases resources associated with it, so code should call cancel as soon as the operations running in this Context complete.
So best practice is to call cancelCtx()
(or whatever you call the function) as soon as you no longer need it (it's fairly common to defer cancel()
even if this means it's called multiple times).
In your example there is another reason that this might be beneficial. Lets assume that the deadline is configurable and has been increased to 5 seconds; now cancelling the context leads to the termination of C2
being triggered by the call cancelCtx()
instead of waiting until the deadline (playground).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论