Pensavo che l’attesa continuasse sullo stesso thread del chiamante, ma non sembra

Ho pensato che uno dei punti su async / await è che quando l’attività viene completata, la continuazione viene eseguita nello stesso contesto in cui è stata richiamata l’attesa, che nel mio caso sarebbe il thread dell’interfaccia utente.

Quindi per esempio:

Debug.WriteLine("2: Thread ID: " + Thread.CurrentThread.ManagedThreadId); await fs.ReadAsync(data, 0, (int)fs.Length); Debug.WriteLine("3: Thread ID: " + Thread.CurrentThread.ManagedThreadId); 

Non mi aspetto questo:

 2: Thread ID: 10 3: Thread ID: 11 

Cosa dà? Perché l’ID del thread per la continuazione è diverso dal thread dell’interfaccia utente?

Secondo questo articolo [^] avrei bisogno di chiamare esplicitamente ConfigureAwait per modificare il comportamento del contesto di continuazione!

Quando si await , per impostazione predefinita, l’operatore await catturerà il “contesto” corrente e lo userà per riprendere il metodo async .

Questo “contesto” è SynchronizationContext.Current meno che non sia null , nel qual caso è TaskScheduler.Current . (Se non è presente un’attività in esecuzione, TaskScheduler.Current è uguale a TaskScheduler.Default , l’ TaskScheduler.Default di TaskScheduler.Default del pool di thread).

È importante notare che un SynchronizationContext o TaskScheduler non implica necessariamente un particolare thread . Un UI SynchronizationContext pianificherà il lavoro sul thread dell’interfaccia utente; ma ASP.NET SynchronizationContext non pianificherà il lavoro su un determinato thread.

Sospetto che la causa del tuo problema sia che stai invocando il codice async troppo presto. Quando si avvia un’applicazione, ha solo un normale thread normale. Quel thread diventa il thread dell’interfaccia utente solo quando fa qualcosa come Application.Run .

L’espressione await utilizzerà il valore di SynchronizationContext.Current per restituire il stream di controllo al thread su cui si è verificato. Nei casi in cui questo è null , verrà TaskScheduler.Current predefinito su TaskScheduler.Current . L’implementazione si basa esclusivamente su questo valore per modificare il contesto del thread al termine del valore dell’attività. Sembra che in questo caso l’ await sia catturare un contesto che non è legato al thread dell’interfaccia utente