Ho letto this question da Noseratio che mostra un comportamento in cui TaskScheduler.Current
non è lo stesso dopo che una versione attendibile ha terminato l'operazione.attendi non riprende il contesto dopo un'operazione asincrona?
La risposta si afferma che:
Se non c'è un compito reale in corso di esecuzione, quindi
TaskScheduler.Current
è lo stesso diTaskScheduler.Default
Il che è vero. Ho già visto here:
TaskScheduler.Default
- restituisce un'istanza della
ThreadPoolTaskScheduler
TaskScheduler.Current
- Se viene chiamato dall'interno di un compito di eseguire restituirà il
TaskScheduler
di il compito attualmente in esecuzione- Se chiamato da qualsiasi altro posto tornerà
TaskScheduler.Default
Ma poi ho pensato, se è così, cerchiamo di fare creare un vero e proprio Task
(e non solo Task.Yield()
) e testarlo:
async void button1_Click_1(object sender, EventArgs e)
{
var ts = TaskScheduler.FromCurrentSynchronizationContext();
await Task.Factory.StartNew(async() =>
{
MessageBox.Show((TaskScheduler.Current == ts).ToString()); //True
await new WebClient().DownloadStringTaskAsync("http://www.google.com");
MessageBox.Show((TaskScheduler.Current == ts).ToString());//False
}, CancellationToken.None, TaskCreationOptions.None,ts).Unwrap();
}
Primo messaggio è "Vero", se cond è "False"
Domanda:
Come potete vedere, ho creato un vero e proprio compito.
Posso capire perché il primo MessageBox produce True
. Quello è becuase del:
Se chiamato dall'interno di un compito di eseguire restituirà il TaskScheduler del compito attualmente in esecuzione
E questo compito non hanno ts
che è l'inviato TaskScheduler.FromCurrentSynchronizationContext()
Ma perché il contesto è non conservato allo secondo MessageBox? Per me, non era chiaro dalla risposta di Stephan.
Ulteriori informazioni:
Se scrivo invece (del secondo messagebox):
MessageBox.Show((TaskScheduler.Current == TaskScheduler.Default).ToString());
lo fa cedere true
. Ma perché ?
Ottima domanda, ma cosa succede se "Utilità di pianificazione! = Contesto di sincronizzazione"? – AgentFire
Un buon caso per la regola hard: non assumere mai 'TaskScheduler.Current' è quello che pensi che sia :) È garantito che sia quello che hai passato a 'Factory.StartNew' per l'ambito dell'azione task lambda (che è' Func' nel tuo caso e restituisce quando colpisce il primo ' await'). Qualsiasi altro comportamento dovrebbe essere trattato come dettagli di implementazione. –
Noseratio