W mojej aplikacji Metro C # / XAML jest przycisk, który uruchamia długotrwały proces. Tak więc, zgodnie z zaleceniami, używam async / await, aby upewnić się, że wątek interfejsu użytkownika nie zostanie zablokowany:
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
await GetResults();
}
private async Task GetResults()
{
// Do lot of complex stuff that takes a long time
// (e.g. contact some web services)
...
}
Czasami rzeczy dziejące się w GetResults wymagały dodatkowego wkładu użytkownika, zanim będzie można je kontynuować. Dla uproszczenia powiedzmy, że użytkownik musi po prostu kliknąć przycisk „kontynuuj”.
Moje pytanie brzmi: jak mogę zawiesić wykonanie GetResults tak, aby czekało na zdarzenie, takie jak kliknięcie innego przycisku?
Oto brzydki sposób na osiągnięcie tego, czego szukam: moduł obsługi zdarzenia dla przycisku kontynuuj ”ustawia flagę ...
private bool _continue = false;
private void buttonContinue_Click(object sender, RoutedEventArgs e)
{
_continue = true;
}
... a GetResults okresowo sonduje to:
buttonContinue.Visibility = Visibility.Visible;
while (!_continue) await Task.Delay(100); // poll _continue every 100ms
buttonContinue.Visibility = Visibility.Collapsed;
Ankieta jest wyraźnie okropna (zajęte oczekiwanie / marnowanie cykli) i szukam czegoś opartego na wydarzeniach.
Jakieś pomysły?
Tak przy okazji, w tym uproszczonym przykładzie jednym rozwiązaniem byłoby oczywiście podzielenie GetResults () na dwie części, wywołanie pierwszej części z przycisku Start i drugiej części z przycisku Kontynuuj. W rzeczywistości rzeczy dziejące się w GetResults są bardziej złożone i różne typy danych wejściowych użytkownika mogą być wymagane w różnych punktach wykonywania. Tak więc rozbicie logiki na wiele metod byłoby nietrywialne.
ManualResetEvent(Slim)
nie wydaje się wspieraćWaitAsync()
.