2012-04-08 12 views
6

Próbuję wykonać działanie w tle, bez blokowania interfejsu użytkownika.Uruchamianie długich zadań bez zamrożenia interfejsu użytkownika

Oczywiście, mógłbym użyć BackgroundWorker do tego.

Jednak chciałbym to zrobić tylko za pomocą interfejsu API zadań.

Próbowałem:

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

i

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


// It freezes the UI 

Więc powinienem wrócić do BackgroundWorker? A może istnieje rozwiązanie korzystające tylko z Tasks?

+0

Dlaczego tak wielu ludzi nie lubi BackgroundWorker? Podoba mi się i znajduję składnię wprost. – Paparazzi

+0

'BackgroundWorker' jest znacznie lepszy niż" Thread ", ale API oparte na zadaniach ostatecznie zdominuje. Mam [powiązany wpis na blogu] (http://nitoprograms.blogspot.com/2010/08/various-implementations-of-asynchronous.html). 'Task.Run' ma następujące zalety: (1) umożliwia zagnieżdżanie; (2) wsparcie anulowania wykorzystuje zunifikowany system 'CancellationToken'; (3) wyjątki są propagowane bardziej naturalnie dzięki poprawnemu stosowi wywołań; (4) wyniki są uzyskiwane bardziej naturalnie; (5) wykorzystuje mniej zasobów (pulę wątków zamiast dedykowanego wątku). –

Odpowiedz

12

Byłeś bardzo blisko.

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

asyncdoes not execute a method on a thread pool thread.

Task.Run wykonuje operację na wątku puli wątków i zwraca wartość Task reprezentującą tę operację.

Jeśli używasz Task.Wait w metodzie async, jesteś doing it wrong. Powinieneś: await wykonywać zadania metodami, nigdy nie blokować ich.

+0

Czy byłaby jakakolwiek różnica, gdybyś nie używał async lub nie oczekiwał w tym konkretnym przykładzie? – Lukazoid

+0

@Lukazoid: Jeśli masz na myśli tylko 'Task.Run' bez' czekania na niego, to po cichu połknie wszystkie wyjątki z 'LongOperation'. –

+0

Ale czy wyjątki nie zostaną połknięte, ponieważ 'OnTestLoaded' jest' async void'? Ach, z dalszego czytania wydaje się, że przy użyciu async void, wyjątek zostałby ponownie użyty na 'SynchronizationContext' przechwycony na początku, bez async/czekać, to byłoby połknięte, jak powiedziałeś, czy to prawda? – Lukazoid

Powiązane problemy