Sono un modo sostanziale attraverso lo sviluppo di una notevole applicazione WPF che controllerà un sofisticato hardware tramite comunicazioni seriali. In fondo all'applicazione "stack" ho un livello di comunicazione seriale (utilizzando la classe .Net "SerialPort"). Leggere e scrivere sul dispositivo h/w è una parte fondamentale del sistema, utilizzata da molte aree diverse del livello della logica aziendale, spesso intervallate da complessi calcoli scientifici e altre logiche simili; questi metodi BLL sono a loro volta chiamati da tutto il livello dell'interfaccia utente.Devo usare async "fino in fondo" per la mia app GUI?
Attualmente, tutto nel livello della logica aziendale, compresa la lettura e la scrittura SerialPort, è sincrono. L'unica volta che utilizzo async/await è nel livello UI, in genere quando si richiama la logica aziendale. Qui io avvolgere la chiamata in Task.Run()
, e.g.:-
private async void SomeButtonClick(object sender, EventArgs e)
{
await Task.Run(() => _someBLLService.TurnPumpOn());
}
Questo è un semplice esempio che prende una questione di millisecondi. Un esempio più complesso sarebbe l'avvio di un processo di lunga durata (sempre utilizzando la tecnica sopra); questo "servizio" di logica aziendale verrà eseguito per alcuni secondi o minuti, raccogliendo dati dall'hardware ed eseguendo altre funzioni di "controllo" durante questo periodo. Periodicamente trasmetterà i dati all'interfaccia utente per il tracciamento su un grafico (tramite un framework di aggregazione di eventi pubsub). La tecnica di cui sopra funziona bene, consentendo all'interfaccia utente di rimanere reattiva mentre si svolgono tali processi di livello aziendale.
Ho preso in considerazione l'idea di passare "asincrono completamente", iniziando dal codice di comunicazione seriale (ad esempio utilizzando .ReadAsync
), ma ciò avrebbe ripercussioni su tutto il sistema. Decine (se non centinaia) di metodi di business logic dovrebbero essere rifattorizzati in metodi asincroni, fino al livello dell'interfaccia utente. Qui vorrei essere in grado di semplificare un po 'il codice di cui sopra:
private async void SomeButtonClick(object sender, EventArgs e)
{
await _someBLLService.TurnPumpOn();
}
Mentre io non sono contrario a affrontare grandi lavori di refactoring, mi chiedo quali sono i benefici sono davvero. Un sacco di persone (come Stephen Cleary) sostengono la soluzione "async all the way", ma l'obiettivo principale sembra essere quello di mantenere l'interfaccia utente reattiva quando chiama un processo BLL di lunga durata, che già fa la mia tecnica Task.Run()
.
Per chiarire, "async all the way" è un altro modo per dire "non bloccare il codice asincrono" - va solo in un modo.Nel caso di un'app dell'interfaccia utente, il principale vantaggio di async è la reattività e 'attendere Task.Run' è una soluzione perfetta se questo funziona per te. –