L’uso di async / await crea un nuovo thread?

Sono nuovo di TPL e mi chiedo: in che modo il supporto di programmazione asincrono che è nuovo a C # 5.0 (tramite il nuovo async e await parole chiave) riguarda la creazione di thread?

Nello specifico, l’uso di async/await crea un nuovo thread ogni volta che vengono utilizzati? E se ci sono molti metodi nidificati che usano async/await , è un nuovo thread creato per ciascuno di questi metodi?

In breve NO

Dalla programmazione asincrona con Async e attendere: Thread

Le parole chiave asincrone e attese non provocano la creazione di thread aggiuntivi. I metodi asincroni non richiedono il multithreading perché un metodo asincrono non viene eseguito sul proprio thread. Il metodo viene eseguito nel contesto di sincronizzazione corrente e utilizza il tempo sul thread solo quando il metodo è attivo. È ansible utilizzare Task.Run per spostare il lavoro associato alla CPU a un thread in background, ma un thread in background non è di aiuto con un processo che attende solo che i risultati diventino disponibili.

Quindi ho letto il modello di threading e Async / Await può sicuramente portare a nuovi thread in uso (non necessariamente creati – il pool li crea all’avvio dell’applicazione). Spetta allo scheduler determinare se è necessario un nuovo thread. E come vedo, una chiamata a una funzione attendibile può avere dettagli interni che aumentano le possibilità che lo schedulatore usi un altro thread; semplicemente perché più lavoro significa più opportunità / ragioni per lo scheduler di dividere il lavoro.

Le operazioni asincrone di WinRT avvengono automaticamente nel pool di thread. In genere chiamerai dal pool di thread, ad eccezione del lavoro sul thread dell’interfaccia. Xaml / Input / Events.

Le operazioni asincrone avviate sui thread Xaml / UI hanno i risultati restituiti al thread dell’interfaccia utente [chiamante]. Ma i risultati dell’operazione asincrona avviati da un thread pool di thread vengono consegnati ovunque avvenga il completamento, che potrebbe non essere lo stesso thread in cui ci si trovava prima. Il motivo alla base di questo è che il codice scritto per il pool di thread è probabilmente scritto per essere thread-safe ed è anche per l’efficienza, Windows non deve negoziare quel thread switch.

Quindi, ancora una volta, in risposta all’OP, i nuovi thread non vengono necessariamente creati ma l’applicazione può utilizzare e utilizzerà più thread per completare il lavoro asincrono.

So che questo sembra contraddire parte della letteratura riguardante async / await, ma questo perché sebbene il costrutto asincrono / atteso non sia di per sé multithreaded. Inarrivabili sono, o uno dei meccanismi con cui lo scheduler può dividere il lavoro e build chiamate attraverso i thread.

Questo è al limite delle mie conoscenze in questo momento riguardo async e threading, quindi potrei non averlo esattamente giusto, ma penso che sia importante vedere la relazione tra attendibili e threading.

L’utilizzo di Async / Attesa non causa necessariamente la creazione di un nuovo thread. Ma l’uso di Async / Await può portare a creare un nuovo thread perché la funzione attendibile può generare un nuovo thread internamente. E spesso accade, rendendo praticamente inutile la frase “No, non genera thread”. Ad esempio, il codice seguente genera nuovi thread.

 VisualProcessor.Ctor() { ... BuildAsync(); } async void BuildAsync() { ... TextureArray dudeTextures = await TextureArray.FromFilesAsync(…); } public static async Task FromFilesAsync(...) { Debug.WriteLine("TextureArray.FromFilesAsync() T1 : Thread Id = " + GetCurrentThreadId()); List files = new List(); foreach (string path in paths) { if (path != null) files.Add(await Package.Current.InstalledLocation.GetFileAsync(path)); // << new threads else files.Add(null); } Debug.WriteLine("TextureArray.FromFilesAsync() T2 : Thread Id = " + GetCurrentThreadId()); ... }