[英]Stop a goroutine if it is running
我有一個類似於How to stop a goroutine with a small twist 的問題。 我不確定 goroutine 是否正在運行。
var quit = make(chan bool)
func f1() {
go func() {
t := time.NewTimer(time.Minute)
select {
case <-t.C:
// Do stuff
case <-quit:
return
}
}()
}
func f2() {
quit <- true
}
如果f2()
在f1()
之后不到一分鍾被調用,則 goroutine 返回。 但是,如果它在一分鍾之后被調用,goroutine 將已經返回並且f2()
將阻塞。 如果 goroutine 正在運行,我希望f2()
取消它,否則什么也不做。
我在這里想要實現的是當且僅當它沒有在創建后的一分鍾內被取消時才執行任務。
說明:
f2()
被多次調用。f1()
的調用者將確保每分鍾調用它不超過一次。使用上下文。
使用可能被取消的上下文運行f1
。 使用關聯的取消 function 運行f2
。
func f1(ctx context.Context) {
go func(ctx context.Context) {
t := time.NewTimer(time.Minute)
select {
case <-t.C:
// Do stuff
case <-ctx.Done():
return
}
}(ctx)
}
func f2(cancel context.CancelFunc) {
cancel()
}
稍后,為了協調這兩個功能,您可以這樣做:
ctx, cancel := context.WithCancel(context.Background())
f1(ctx)
f2(cancel)
您還可以嘗試使用context.WithTimeout
function 來合並外部定義的超時。
如果你不知道是否有一個 goroutine 已經在運行,你可以像上面一樣初始化ctx
和cancel
變量,但不要將它們傳遞給任何東西。 這避免了檢查nil
。
請記住將 ctx 和 cancel 視為要復制的變量,而不是引用,因為您不希望多個 goroutine 共享 memory - 這可能會導致競爭條件。
您可以給通道一個緩沖區大小為 1。這意味着您可以在不阻塞的情況下向它發送一個值,即使該值沒有立即(或根本沒有)接收到。
var quit = make(chan bool, 1)
我認為最佳答案更好,這只是另一種可以轉化為其他情況的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.