2012-12-18 9 views
7

Przeczytałem, że "BackgroundWorker" jest designed to be replaced przez Ansyc/Await.Czy oczekujesz, że reszta metody będzie asynchroniczna?

Ponieważ lubię skondensowany wygląd Async/Await, zaczynam konwertować niektóre z moich BackgroundWorkers na wywołania Async/Await.

To jest przykład kodu mam (zwanej od UI):

public async void RunFromTheUI() 
{ 
    await OtherAction(); 
} 

public async void OtherAction() 
{ 
    var results = await services.SomeRemoteAction(); 

    foreach (var result in results) 
    { 
     result.SemiIntenseCalculation(); 
     Several(); 
     Other(); 
     NonAsync(); 
     Calls(); 
    } 

    SomeFileIO(); 
} 

Kiedy zadzwonić RunFromTheUI powróci niemal natychmiast (zgodnie z Async i czekać na projekt).

Jednak po wznowieniu po zakończeniu services.SomeRemoteAction() ma pętlę foreach i inne wywołanie metody, które należy wykonać.

Moje pytanie brzmi: Jeśli ta pętla to świnia wydajności, to zablokuje interfejs użytkownika? (Zanim miałem wszystko w wątku pracującym w tle, więc nie spowolnił interfejsu użytkownika).

Uwaga: Wybieram system .Net 4.0 i używam pakietu Async Nuget.

+0

async/await i BackgroundWorker rozwiązują dwa różne problemy. Pracownik BG zostaje precyzyjniej zastąpiony Zadaniami. Async zastępuje je tylko wtedy, gdy kod ciała pracownika jest w zasadzie bezczynny, gdzie BGW/Tasks są nadal przydatne, gdy trzeba wykonać ciężki lifting. Wygląda na to, że czekasz na wyniki usługi na twoim pytaniu, tylko na to. –

+0

1. Twój kod się nie skompiluje, nie możesz "poczekać" na metodę "async void". 2. Nie powinieneś używać metod 'async void', nie można ich" oczekiwać "i utrudniać obsługę wyjątków. – svick

Odpowiedz

6

Moje pytanie brzmi: czy ta pętla jest hogiem wydajności, czy zablokuje interfejs użytkownika?

Tak, będzie. Reszta metody asynchronicznej będzie nadal wykonywana w wątku interfejsu użytkownika po zakończeniu działania zdalnego. Jeśli nie chcesz, aby tak się stało, to są opcje:

  • Zastosowanie ConfigureAwait(continueOnCapturedContext: false) tak, że kontynuacja nie ma wykonać na wątku UI
  • wykonać całość metody w innym wątku na początek, używając Task.Run. (Możesz nadal zrobić to metodą asynchroniczną, aby uniknąć zablokowania wątku, gdy nie potrzebujesz).

Zasadniczo, jeśli masz ładunek synchroniczny, blokowanie połączeń lub praca wymagająca dużego obciążenia procesora , chcesz uniknąć tego w wątku UI, który jest domyślnie przeciwny do tego, co async/await.

+1

'Task.Run' ma lepsze ustawienia domyślne niż' Task.Factory.StartNew', jeśli używasz 'async'. [Stephen Toub wchodzi w szczegóły.] (Http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx) –

+0

@StephenCleary: Naprawiono, dziękuję. Nie zwracałem uwagi - "Task.StartNew" nie był ważny, oczywiście :) –

+0

Jon: Czy jest dobry punkt wyjścia do czytania/rozumienia asynchronicznego/oczekiwania, zadania? – shahkalpesh