Async / await rende la cosa semplice non necessaria complicata?

5

Dopo aver esposto allo sviluppo di Windows App Store per un mese, comincio a pensare che il modello di programmazione async / await faccia più male che bene. Rende complicata la cosa semplice.

Fai un esempio, creazione di cartelle. In Java o Desktop .NET, posso semplicemente fare

Java

public Constructor()
{
    new File("c:\folder").mkdirs();
    System.out.println("I am pretty sure c:\folder is ready now");
}

Desktop .NET

Constructor()
{
    System.IO.Directory.CreateDirectory("c:\folder");
    Console.WriteLine("I am pretty sure c:\folder is ready now");
}

Ma quando arriva a

App Store Windows .NET

Constructor()
{
    // Damm it! Another async function? I don't need aysnc!
    Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync("c:\folder", CreationCollisionOption.OpenIfExists);
    // I am not sure c:\folder is ready right now!
    // OK. I know I can use ContinueWith. No no no. I don't want.
    // Why I have to use ContinueWith with such a simple operation?
}

Quindi, la mia domanda è: trovi il nuovo modello di programmazione async / await in Windows App Store,

  • Migliora la tua produttività?
  • Semplifica la programmazione?

Per me, io no! Forse mi mancano alcune tecniche utili.

Lo so, Microsoft dice, ci aiuta a scrivere codice UI reattivo.

Ma direi, No, grazie! Hey guarda, il mio codice è già in codice non UI!

La maggior parte del mio codice operativo corrente è abbastanza veloce e non blocca l'interfaccia utente. Quando il mio codice operativo non è abbastanza veloce, mi sento piuttosto a mio agio nel far funzionare quei codici operativi lenti in Thread / Task separati.

Costringendomi a utilizzare async / await di cui non ho bisogno, rende solo più complicato il mio codice.

Messaggio a Microsoft : posso supplicarti, oltre alle funzioni asincrone, di fornire una serie di funzioni non asincrone, per favore? Ho già sviluppato la mia abitudine di eseguire il codice nel thread non dell'interfaccia utente. Prometto che continuerò a fare in modo che l'app per Windows funzioni senza problemi come iOS:)

    
posta Cheok Yan Cheng 28.11.2012 - 16:18
fonte

7 risposte

10

Probabilmente sei ritenendolo sbagliato (solo un contesto per il dichiarazione) .

Purtroppo non ho ancora avuto la possibilità di giocare con Win8, ma sulla base degli esempi di codice che ho visto, il tuo codice dovrebbe apparire più come

Constructor()
{
    // Damm it! Another async function? I don't need aysnc!
    var result = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync("c:\folder", CreationCollisionOption.OpenIfExists);
    // by the time your code gets to this line, the folder will have been created
}

L'altra opzione (se non è possibile rendere il metodo async ) consiste nel bloccare il thread fino al completamento dell'operazione asincrona chiamando GetResults . Probabilmente qualcosa sulla falsariga di

Constructor()
{
    // Damm it! Another async function? I don't need aysnc!
    var result = Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync("c:\folder", CreationCollisionOption.OpenIfExists);
    result.GetResults();
    result.Close(); // According to documentation, you should call this when done
    // Voila, 
}

Anche se sembra che tu stia facendo un file IO all'interno di un costruttore e probabilmente non puoi avere costruttori di async , quindi la prima opzione è fuori. Presumo che questo sia solo un esempio forzato e non rappresentativo del tuo codice, ma la mia sensazione è che se ti trovi a fare IO all'interno di un costruttore e non stai scrivendo una classe framework (come FileInfo ), dovresti dare una seconda occhiata al tuo progetto. Generalmente non mi aspetto che la creazione di una classe inizi a creare / bloccare le risorse di sistema.

Ci sono un paio di domande correlate su StackOverflow riguardanti costruttori e asincroni

risposta data 28.11.2012 - 17:20
fonte
13

Il problema qui non è le parole chiave async / await ma il fatto che molte API WinRT sono offerte solo in forma asincrona. In passato, le API sono state offerte in una forma di blocco, o la scelta di bloccare e non bloccare, e gli sviluppatori dovevano assicurarsi che l'interfaccia utente non si bloccasse. Beh indovina cosa? Gli sviluppatori non si sono disturbati. Ho aspettato più minuti per una finestra di dialogo Stampa in un prodotto Office per terminare il timeout di contattare qualsiasi stampante che ho usato l'ultima volta, prima che potessi specificare che non voglio quella stampante, di solito perché quella stampante è ora a migliaia di chilometri da me. La maggior parte delle applicazioni è stata scritta in modo semplice per lo sviluppatore, anche se ciò potrebbe creare un'esperienza negativa per l'utente.

Quindi la nuova API non ha alcun modulo di blocco. Devi imparare come farlo in modo asincrono, piaccia o no. È possibile impostare un gestore completato e quindi avviare il processo oppure utilizzare le nuove parole chiave C #. La tua scelta. Ma gli sviluppatori non saranno più affidabili per mantenere la promessa che offri di fare. E giustamente, dal momento che quasi nessuno ha fatto.

    
risposta data 28.11.2012 - 17:22
fonte
4

Penso che, in una sorta di partenza per Microsoft, hanno pensato a cosa rende la migliore esperienza utente piuttosto che a ciò che rende l'esperienza di sviluppo più semplice.

Sicuramente l'adozione del modello asincrono richiede più lavoro da parte dello sviluppatore, ma forse offre allo sviluppatore una maggiore possibilità di produrre qualcosa che risponda all'utente.

Devi solo utilizzare Outlook per vedere quanto può essere pessima l'esperienza utente se segui troppo un modello di programmazione sincrono.

    
risposta data 28.11.2012 - 16:48
fonte
2

await è stato introdotto con .NET v4.5 ed è in realtà un modo per rompere il puro approccio asincrono. Quindi è lì come un modo per semplificare la codifica con metodi / chiamate asincroni.

Può anche essere abusato se si inserisce await su ogni singola chiamata. A quel punto, sei tornato agli stili di codifica "tradizionali" in cui devi aspettare che tutte le azioni vengano restituite.

Asynch è un approccio utile quando si effettuano chiamate attraverso una rete o quando altre azioni possono continuare in attesa dei risultati della chiamata. È equivalente all'utilizzo di un thread in background per gestire una qualche forma di elaborazione dei dati. Il resto dell'app continua fino a quando l'attività è terminata.

Come hai notato nel tuo esempio, ci sono alcuni casi in cui devi semplicemente attendere fino al completamento della chiamata prima che le operazioni possano continuare. Ecco dove la parola chiave await è utile. Un'alternativa era avere un metodo di callback che eseguiva il resto dell'elaborazione. Onestamente, quell'alternativa è meno che elegante, e sono contento che sia stato offerto await .

Quindi, proprio come con qualsiasi altro strumento:

  • Utilizza metodi asincroni appropriati per le chiamate effettuate dall'app.
  • Utilizza la parola chiave await con giudizio quando ci sono chiamate che devono davvero bloccare il resto delle operazioni. Non abusare della parola chiave in quanto ciò ostacolerebbe la tua applicazione.
risposta data 28.11.2012 - 16:37
fonte
2

In realtà, Async / Await rende molto più semplice una cosa inutilmente complicata. (Provate a immaginare se doveste fare tutto ciò che senza Async / Await!) La parte inutilmente complicata è la decisione di Microsoft di rendere tutte quelle API async-only, invece di lasciarlo a discrezione degli sviluppatori .

    
risposta data 28.11.2012 - 17:44
fonte
2

Vedo che il problema qui è che non è possibile utilizzare Attendere in un costruttore e che GetResult non funzionerà. Ma hai pensato di utilizzare un metodo di supporto statico per creare il tuo oggetto?

class AsyncCreated
{
    public static async Task<AsyncCreated> CreateWithFolder()
    {
        var folder = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync("c:\folder", CreationCollisionOption.OpenIfExists);

        return new AsyncCreated(folder); // There you do the usual stuff
    }

}

// elsewhere in your code

var myObject = await AsyncCreated.CreateWithFolder();

Il bonus aggiuntivo è che ora è più esplicito che si sta facendo del lavoro mentre si inizializza il tipo.

    
risposta data 20.12.2012 - 19:28
fonte
1

Potrebbe.

Ma quello che probabilmente sta realmente accadendo è che è mantenere complicate cose complicate.

La creazione di un file è complicata. Può essere su una condivisione di rete. Può già esistere. Il disco rigido potrebbe essere lento. Potrebbe essere un disco RAM. Il punto è che può richiedere diverse quantità di tempo o potrebbe fallire a priori.

Jeff Atwood ha scritto un ottimo post su questo 8 anni fa . Sostanzialmente ha detto che noi dovremmo abbracciare il codice multithreading e asincrono, ma la maggior parte degli sviluppatori non è disposta ad affrontarlo perché è un argomento molto complesso e gli strumenti non erano adatti a farlo abbastanza facile da scrivere codice asincrono.

Le parole chiave async e await (insieme ad altri strumenti, come le raccolte thread-safe) sono la risposta di Microsoft alla sua richiesta di migliorare gli strumenti per portare una programmazione asincrona facile alle masse non lavate. La mia opinione è che ci sono riusciti per lo più. Nella maggior parte dei casi, è possibile utilizzare le API asincrone in WinRT come se non fossero asincrone, quindi aggiungere pepe in poche parole async e await , compilare e utilizzare il codice reattivo, non bloccante .

I costruttori, così come alcune altre cose, sono dove i limiti degli strumenti appaiono e fanno scattare anche il programmatore medio, che sta solo cercando di scrivere un programma per fare il suo lavoro.

Jeff ha anche commentato che uno dei motivi per cui BeOS non è riuscito ad attirare sviluppatori era perché, come WinRT, l'intera API del sistema operativo era asincrona, e scrivere qualsiasi cosa al di là di un'utilità era tortura. Penso che per la maggior parte sia una piccola curva di apprendimento, ma gli strumenti sono molto più accessibili di quanto non fossero 8 anni fa. Vedremo come valuterà Microsoft in futuro.

    
risposta data 20.12.2012 - 22:04
fonte

Leggi altre domande sui tag