Nella mia app metro C # / XAML, c'è un pulsante che avvia un processo di lunga durata. Quindi, come raccomandato, sto usando async / await per assicurarmi che il thread dell'interfaccia utente non venga bloccato:
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)
...
}
Di tanto in tanto, le cose che accadono all'interno di GetResults richiedono un input aggiuntivo da parte dell'utente prima di poter continuare. Per semplicità, supponiamo che l'utente debba semplicemente fare clic su un pulsante "continua".
La mia domanda è: come posso sospendere l'esecuzione di GetResults in modo tale da attendere un evento come il clic di un altro pulsante?
Ecco un brutto modo per ottenere ciò che sto cercando: il gestore di eventi per il pulsante continua "imposta una bandiera ...
private bool _continue = false;
private void buttonContinue_Click(object sender, RoutedEventArgs e)
{
_continue = true;
}
... e GetResults lo interroga periodicamente:
buttonContinue.Visibility = Visibility.Visible;
while (!_continue) await Task.Delay(100); // poll _continue every 100ms
buttonContinue.Visibility = Visibility.Collapsed;
Il polling è chiaramente terribile (attesa impegnata / spreco di cicli) e sto cercando qualcosa basato sugli eventi.
Qualche idea?
In questo esempio semplificato, una soluzione sarebbe ovviamente quella di dividere GetResults () in due parti, invocare la prima parte dal pulsante di avvio e la seconda parte dal pulsante continua. In realtà, le cose che accadono in GetResults sono più complesse e diversi tipi di input dell'utente possono essere richiesti in diversi punti dell'esecuzione. Quindi suddividere la logica in più metodi non sarebbe banale.
ManualResetEvent(Slim)
non sembra supportareWaitAsync()
.