2012-04-08 6 views
6

Ich versuche eine Aktion im Hintergrund auszuführen, ohne die Benutzeroberfläche zu blockieren.Lange Aufgaben ausführen, ohne die Benutzeroberfläche zu blockieren

Natürlich könnte ich BackgroundWorker dafür verwenden.

Allerdings möchte ich es nur mit der Task-API tun.

Ich habe versucht:

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

und

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


// It freezes the UI 

Also muss ich mich zurück Background? Oder gibt es eine Lösung, die nur Aufgaben verwendet?

+0

Warum mögen so viele Leute BackgroundWorker nicht? Ich mag es und finde die Syntax direkt. – Paparazzi

+0

'BackgroundWorker' ist viel besser als' Thread', aber 'Task'-basierte APIs werden schließlich dominieren. Ich habe [einen verwandten Blogbeitrag] (http://nitoprograms.blogspot.com/2010/08/various-implementations-of-asynchronous.html). 'Task.Run' hat die folgenden Vorteile: (1) erlaubt das Verschachteln; (2) die Stornierungsunterstützung verwendet das vereinheitlichte "CancellationToken" -System; (3) Ausnahmen werden natürlicher mit einem korrekten Aufrufstapel verbreitet; (4) Ergebnisse werden natürlicher abgerufen; (5) verwendet weniger Ressourcen (Thread-Pool statt dedizierten Thread). –

Antwort

12

Sie waren ziemlich nah dran.

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

asyncdoes not execute a method on a thread pool thread.

Task.Run führt eine Operation für einen Threadpool-Thread aus und gibt eine Task zurück, die diese Operation darstellt. Wenn Sie Task.Wait in einer async-Methode verwenden, sind Sie doing it wrong. Sie sollten await Aufgaben in async Methoden, nie auf ihnen blockieren.

+0

Wäre es ein Unterschied, wenn Sie in diesem speziellen Beispiel nicht async verwenden oder warten würden? – Lukazoid

+0

@Lukazoid: Wenn du nur "Task.Run" meinst, ohne es zu erwarten, dann würde das stillschweigend alle Ausnahmen von 'LongOperation' verschlucken. –

+0

Aber werden die Ausnahmen nicht trotzdem verschluckt, da 'OnTestLoaded' eine' async void' ist? Ah, aus weiterem Lesen, scheint es, wenn async void verwendet wird, würde die Ausnahme auf dem "SynchronizationContext", der zu Beginn gefangen wurde, ohne async/await zurückgeworfen werden, würde es verschluckt werden, wie Sie sagten, ist das korrekt? – Lukazoid

Verwandte Themen