2012-04-08 5 views
6

Sto tentando di eseguire un'azione in background, senza congelare l'interfaccia utente.Esecuzione di attività lunghe senza congelare l'interfaccia utente

Ovviamente, potrei usare BackgroundWorker per questo.

Tuttavia, mi piacerebbe farlo solo con l'API delle attività.

ho provato:

async void OnTestLoaded(object sender, RoutedEventArgs e) 
{ 
    await LongOperation(); 
} 
// It freezes the UI 

e

async void OnTestLoaded(object sender, RoutedEventArgs e) 
{ 
    var task = Task.Run(()=> LongOperation()); 
    task.Wait(); 
} 


// It freezes the UI 

Quindi devo tornare a BackgroundWorker? O esiste una soluzione solo con Google Task?

+0

Perché così tante persone non amano BackgroundWorker? Mi piace e trova la sintassi diretta. – Paparazzi

+0

'BackgroundWorker' è molto meglio di' Thread', ma alla fine domineranno le API basate su Task'. Ho [un post sul blog correlato] (http://nitoprograms.blogspot.com/2010/08/various-implementations-of-asynchronous.html). 'Task.Run' presenta i seguenti vantaggi: (1) consente il nesting; (2) il supporto per la cancellazione utilizza il sistema unificato 'CancellationToken'; (3) le eccezioni si propagano più naturalmente con uno stack di chiamate corretto; (4) i risultati sono recuperati in modo più naturale; (5) utilizza meno risorse (pool di thread anziché thread dedicati). –

risposta

12

Eri molto vicino.

async void OnTestLoaded(object sender, RoutedEventArgs e) 
{ 
    await Task.Run(() => LongOperation()); 
} 

asyncdoes not execute a method on a thread pool thread.

Task.Run esegue un'operazione su un thread pool di thread e restituisce un Task che rappresenta tale operazione.

Se si utilizza Task.Wait in un metodo async, si è doing it wrong. È necessario eseguire le attività await nei metodi async, non bloccarle mai.

+0

Ci sarebbe qualche differenza se non hai usato async o attendi in questo specifico esempio? – Lukazoid

+0

@Lukazoid: se intendi solo 'Task.Run' senza 'attendere', allora questo ingoia silenziosamente tutte le eccezioni da' LongOperation'. –

+0

Ma le eccezioni non verranno comunque ingoiate perché "OnTestLoaded" è un "vuoto asincrono"? Ah, da ulteriori letture, sembra che quando si usa il vuoto asincrono, l'eccezione verrebbe ripresentata sul 'SynchronizationContext' catturato all'inizio, senza l'async/await, sarebbe inghiottito come hai detto tu, è corretto? – Lukazoid