Ich versuche herauszufinden, wie mit dem Kontextmuster in Go gearbeitet wird. Ich simuliere den Fall, wenn mehrere lang laufende Child-Gououtines wegen Timeout ihrer Ausführung abgebrochen werden müssen. Wie ich verstanden habe, besteht einer der Hauptnutzungen des Kontextes darin, alle Kindprozesse im Falle eines I/O-Timeouts zu stoppen oder wenn der Benutzer die Seite vor dem Ende der Verarbeitung verlässt.Abbrechen der Ausführung von untergeordneten Prozessen mithilfe des Kontexts
Mein Code:
package main
import (
"context"
"fmt"
"time"
)
func doIt(ctx context.Context, filename string) {
// simulate not ending file processing -
// internals of this loop could not change
// e.g. it is call of some third party or stdlib function that hangs
for {
fmt.Printf("processing file %s\n", filename)
time.Sleep(50 * time.Millisecond)
}
}
func main() {
startFileProcessing()
fmt.Println("End of processing")
time.Sleep(500 * time.Millisecond)
fmt.Println("Do something else")
}
func startFileProcessing() {
// set file processing timeout
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*100)
defer cancel()
// start two parallel processes
go doIt(ctx, "file1")
go doIt(ctx, "file2")
select {
case <-ctx.Done():
fmt.Println("file processing timeout")
return
}
}
Welche Ausgänge:
processing file file2
processing file file1
processing file file1
processing file file2
processing file file1
file processing timeout
End of processing
processing file file2
processing file file2
processing file file1
processing file file1
processing file file2
Do something else
Ich erwarte nicht, um zu sehen, "Verarbeitungsdatei" Zeilen nach "Dateiverarbeitung timeout".
Wie es zu beheben?
Bearbeiten: @ Mellow Marmot wies darauf hin, dass der Kontext Kindergououtines nicht auf eigene Faust und vorgeschlagene Lösung für diese zu stoppen. Aber seine Änderungen sind innerhalb der Schleife in doIt Funktion, die die Frage nicht vollständig beantwortet, weil anstelle von Schleife in doIt Funktion könnte es einige Third Party (oder StdLib) Funktionsaufruf, der nicht geändert werden konnte.
Also lassen Sie mich Frage umformulieren -
Wie einige lange laufenden Prozesse zu Interna von denen kündige ich keinen Zugang haben - die für mehr Zeit als Timeout hängt?
danke. Aber der erste Loop-Zyklus sperrt die Zeile "case <-ctx.Done():", bis das Timing abgelaufen ist - das erwarte ich nicht. Ändern Sie es in Wählen Sie { Fall <-ctx.Done(): zurück Standard: } behebt diesen Fehler. – sev3ryn
, aber, wie man einige lang laufende Prozesse zu Internals annulliere, von denen ich keinen Zugang habe - lässt sagen, dass anstelle der Funktion doIt einige Third Party oder stdlib Funktion - für mehr Zeit als Zeitüberschreitung hängt. – sev3ryn
@ sev3ryn Es ist nicht möglich, eine lange laufende Goroutine abzubrechen, es sei denn, der Code, der in der Goroutine ausgeführt wird, bietet einen Mechanismus, um dies zu tun. Es gibt keinen Mechanismus zum Töten einer Goroutine außerhalb des Codes, der in der Goroutine ausgeführt wird. –