Prima un po 'di informazioni di base. Sono in procinto di rendere il codice della libreria C# esistente adatto per l'esecuzione su WinRT. Poiché una parte minore di questo codice in profondità richiede di eseguire un piccolo file di I/O, per prima cosa abbiamo cercato di mantenere le cose sincrone e utilizzato Task.Wait() per interrompere il thread principale fino a quando non è stato eseguito tutto l'IO.Perché task.Attendere il deadlock su un thread non-ui? O sono solo fortunato?
Abbastanza sicuro, abbiamo rapidamente scoperto che porta a un punto morto.
Mi sono quindi ritrovato a modificare molto codice in un prototipo per renderlo "asincrono". Cioè, stavo inserendo async e attendo parole chiave, e stavo cambiando di conseguenza i tipi di ritorno del metodo. Questo è stato un sacco di lavoro - lavoro troppo insensato in effetti -, ma ho ottenuto il prototipo in questo modo.
poi ho fatto un esperimento, e ho eseguito il codice originale con la dichiarazione Wait su un thread separato:
System.Threading.Tasks.Task.Run(()=> Draw(..., cancellationToken)
No stallo!
Ora sono seriamente confuso, perché ho pensato di capire come funziona la programmazione asincrona. Il nostro codice non (ancora) usa ConfigureAwait (false) affatto. Quindi tutte le dichiarazioni attese dovrebbero continuare nello stesso contesto in cui sono state invocate. Giusto? I assunto che significa: la stessa discussione. Ora se questo thread ha invocato "Wait", questo dovrebbe anche portare a un deadlock. Ma non è così.
Qualcuno di voi ha una spiegazione chiara e solida?
La risposta a questo determinerà se davvero passerò attraverso il nostro codice inserendo un sacco di parole chiave condizionali asincrone/attese, o se lo manterrò pulito e useremo solo un thread che fa un Wait() qui e lì. Se le continuazioni vengono eseguite da un thread arbitrario non bloccato, le cose dovrebbero andare bene. Tuttavia, se vengono eseguiti dal thread dell'interfaccia utente, potremmo avere dei problemi se la continuazione è dispendiosa dal punto di vista computazionale.
Spero che il problema sia chiaro. In caso contrario, per favore fatemelo sapere.
Grazie per le informazioni. Questo spiega molto. –
Come fare confusione: questo è il codice di libreria esistente che è mirato su più piattaforme (.Net), non solo su WinRT. Vorremmo utilizzare lo stesso codice per tutte le piattaforme, quindi dobbiamo usare #if per evitare attese/asincrone per le piattaforme in cui non è disponibile. Inoltre, non possiamo semplicemente modificare tutte le API esistenti in quelle asincrone, in quanto ciò potrebbe rompere le cose per i clienti esistenti. Tutte queste istruzioni #if rendono il codice un po 'meno leggibile. –
Trovo che il _idea_ di async/attenda piuttosto attraente e ragionevole. Tuttavia, penso che l'effettiva implementazione fornita da Microsoft sia problematica. Il fatto che la semantica di questi costrutti dipenda dal contesto in cui è stato avviato il thread è un errore, credo. Soprattutto perché la semantica del codice del programma dovrebbe dipendere dal contesto di esecuzione il meno possibile (difficile da ragionare). Posso capire che Microsoft vuole aggiungere opzioni, ma penso che l'uso diretto di attesa e sincronizzazione non dovrebbe introdurre tali differenze. –