Ich verstehe, dass das Blockieren auf Async-Code in den meisten Fällen abgelehnt wird.Blockieren auf async mit Thread.Sleep() & Task.Yield()
Ich habe jedoch eine WPF-Anwendung, die eine Hintergrundaufgabe ausführt. Wenn der Benutzer das Fenster schließt, sollte diese Aufgabe abgebrochen und das Schließen des Fensters verzögert werden, bis die Löschung und anschließende Bereinigung abgeschlossen ist. In der Zwischenzeit sollten weitere Benutzereingaben blockiert werden.
Nach ein bisschen & Suche versucht, kam ich mit dem folgenden Code auf:
ViewModel.cs:
async void RunTaskAsync()
{
_cancelTknSource = new CancellationTokenSource();
try {
await Task.Run(/*...long running calculation...*/, _cancelTknSource.Token);
}
catch (OperationCanceledException) { }
finally {
/*...cleanup...*/
_cancelTknSource.Dispose();
_cancelTknSource = null;
}
}
async Task CancelAsync()
{
_cancelTknSource?.Cancel();
while (_cancelTknSource != null) {
Thread.Sleep(10);
await Task.Yield(); //prevents dead-lock
}
}
Window.xaml.cs:
async void Window_Closing(object sender, CancelEventArgs e)
{
e.Cancel = true;
await DataContext.CancelAsync();
Close();
}
(Alle Diese Methoden werden vom UI-Thread aufgerufen.
Ist dies eine gute Vorgehensweise? Wenn nicht, was sind die Alternativen?
Willkommen gut Sir. Ich frage mich, ob diese Frage vielleicht besser auf der Geschwisterseite _Code Review_ gestellt wird (weil Ihre eher eine Design- als eine Problemfrage ist) im StackExchange-Netzwerk? Viel Glück – MickyD
Task.Yield() nicht Deadlock beheben, löst es nicht das grundlegende Problem, dass der UI-Thread nicht mehr in der Lage ist, Benachrichtigungen zu verarbeiten. Der Hinweis für WPF unterscheidet sich nicht grundlegend von Winforms (https://Stackoverflow.com/a/1732361/17034). –
"Warten auf Task.Run (/ * ... lang laufende Berechnung ... * /, _ cancelTknSource.Token);" wenn Sie auf diese Aufgabe warten. Was ist der Sinn des Tokens? – efekctive