Task Async / Attesa HTTP: evita di sovraccaricare il server con le richieste?

1

Ho uno scenario in cui ho un'applicazione per Windows Store, c'è una pagina con una funzionalità di ricerca, l'utente digita i nomi in una casella di testo e l'app cerca nomi simili al testo digitato.

La ricerca viene effettuata tramite la chiamata a un metodo GET AEST RESTful. la chiamata impiega circa 4 secondi per recuperare i risultati. Questo usa la tecnica c # async / await.

Quello che voglio fare è chiamare il metodo HTTP mentre l'utente digita, ma voglio farlo annullando qualsiasi attività in esecuzione e assicurandomi che venga eseguita una sola attività alla volta per evitare di inondare il server con richieste.

Ho implementato il seguente approccio, funziona bene, ma credo che ci possa essere una soluzione migliore:

  • Conservo un riferimento all'attività asincrona e a una sorgente di token di annullamento.
  • Mentre l'utente digita, controllo se c'è un'attività in esecuzione, la annullo e ne avvio una nuova con il testo di ricerca più recente.

    private CancellationTokenSource cts = null;
    private Task<List<string>> searchTask;
    
    private async void textbox_TextChanged(object sender, TextChangedEventArgs e)
    {
      //there is already running task
      if (searchTask != null && !searchTask.IsCompleted)
        {
          //cancel the running and start a new one
             cts.Cancel();
             cts = new CancellationTokenSource();
           searchTask=SearchWeb(txtbox.Text, cts.Token);
           searchTask.ContinueWith(t =>{
               //show results
           });
      }
      else
      {
          //start a new one
            searchTask = dataRepository.SearchUsers(txtbox.Text, cts.Token);
            searchTask.ContinueWith(t =>{
              //show results
          });
      }
    }
    

La mia preoccupazione principale è che non mi piace l'overhead generato con il monitoraggio delle attività in esecuzione. Sembra che ci dovrebbe essere un modo più efficiente di fare ciò che non richiede la cancellazione di così tante richieste.

    
posta Mina Samy 08.12.2015 - 16:12
fonte

1 risposta

3

Se desideri ridurre il numero di avviamenti e annullamenti, metterei un ritardo nell'esecuzione. Un altro approccio sarebbe utilizzare il polling, ma questo è più generale e più complesso; e viola la buona politica di "Tell, do not ask".

Penso che una cosa del genere possa fare il lavoro di afferrare la stringa di ricerca solo dopo un ritardo, in modo che possano digitare alcuni caratteri prima di afferrarla e iniziare l'esecuzione. Se l'esecuzione è già in corso, si desidera comunque annullare e avviare un altro ritardo. In questo modo, se iniziano e finiscono di digitare prima che il ritardo sia finito, non verrà annullato e in quel momento verrà eseguita la query.

private CancellationTokenSource cts = null;
private Task<List<string>> searchTask;
private Task delayTask;
private string searchString;

private async void textbox_TextChanged(object sender, TextChangedEventArgs e)
{
  searchString = txtbox.Text;

  if (delayTask != null && !delayTask.IsCompleted)
    return;

  //there is already running task
  if (searchTask != null && !searchTask.IsCompleted)
  {
    //cancel the running and start a new one
    cts.Cancel();
    cts = new CancellationTokenSource();
  }

  ExecuteQueryAfterDelay();
}

private void ExecuteQueryAfterDelay()
{
  delayTask = Task.Delay(2000).ContinueWith(t =>
  {
    searchTask=SearchWeb(searchString, cts.Token);
    searchTask.ContinueWith(t =>
    {
      //show results
    });
  });
}
    
risposta data 08.12.2015 - 21:55
fonte

Leggi altre domande sui tag