Mi diverto con async e await e sembrano piuttosto intuitivi, ma alcune delle cose che sto leggendo su queste parole chiave non hanno senso per me. In effetti, alcuni di questi mi sembrano sbagliati, o almeno fuorvianti, anche se provengono direttamente da Microsoft. Considera il seguente codice:
namespace AsyncExample2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
var t=new Task<int>(longRunningWork);
t.Start();
int r= await t;
textBox1.Text += (r.ToString());
}
int longRunningWork()
{
Thread.Sleep(15000);
return (new Random()).Next(10);
}
}
}
Questo è da un'applicazione di esempio WinForms che ho creato con una GUI composta da un singolo pulsante e una singola casella di testo. Quando si preme il pulsante, 15 secondi dopo, una cifra casuale viene aggiunta al testo nella casella di testo. Durante questo periodo di 15 secondi, la GUI rimane interattiva, ad es. il modulo può essere massimizzato / minimizzato / spostato. Il pulsante può anche essere cliccato di nuovo.
Il modo più semplice in cui questo codice sembra contraddire ciò che Microsoft dice di attendere / async è che, secondo loro, la mia chiamata a t.Start () non dovrebbe essere necessario. Considera la primissima affermazione dell'articolo al link : "[i] n un metodo asincrono, le attività vengono avviate quando vengono create. " Questo non sembra essere il caso in questo particolare metodo async ( button1_Click ), sebbene l'abbia visto accadere in altri contesti.
In secondo luogo, ho letto molto di ciò che descriverei come tentativi aggressivi di differenziare il vecchio modello basato su thread del parallelismo e async / attendere , e , come il "Tutto nuovo!" le etichette applicate spesso agli imballaggi dei prodotti da parte dei reparti marketing aziendali, questi tentativi di differenziazione sembrano contenere alcune spinte ingiustificate.
Considera la frase che "le parole chiave async e await non provocano la creazione di thread aggiuntivi" (da link ). Questa non è la mia osservazione; se controllo Thread.CurrentThread.ManagedThreadId , posso vedere che longRunningWork () non è in esecuzione sul thread della GUI, sebbene button1_Click lo sia certamente. Inoltre, se faccio clic sul pulsante rapidamente in successione e ispeziono Thread.CurrentThread.ManagedThreadId alla chiamata a Thread.Sleep () , vedo vari ID thread gestiti diversi . E se provo ad aggiungere qualcosa a longRunningWork () che influenza la GUI (ad esempio, imposta textBox1.Text ), ottengo il tipico errore "chiamata cross-thread illegale" .
Qualcuno può aiutarmi a conciliare queste apparenti incoerenze? La mia impressione è che la prima incongruenza che evidenzi sia un esempio relativamente piccolo di sciatteria (anche se mi piacerebbe davvero sapere quando devo chiamare Start () manualmente).
La seconda incoerenza, sospetto, è solo pedanteria. Le persone che conoscono un po 'di async / await amano correggere i noobs che non possono parlare di queste parole chiave senza pensare in termini di thread. Capisco; è un modello diverso di parallelismo con un modo di pensare completamente diverso. Allo stesso tempo, tuttavia, è un oversell preciso dire che "le parole chiave async e await non provocano la creazione di thread aggiuntivi." Il debugger implica diversamente.
Suppongo che tecnicamente sia possibile che i thread che sto vedendo vengano catturati da una sorta di pool che esiste durante l'esecuzione del programma. Se questo è il caso, quindi, tecnicamente, niente viene creato da async / await . Questo mi sembra piuttosto banale, e non sono a conoscenza del fatto che i programmi WinForms abbiano un pool di thread in stile ASP.NET.