2015-02-23 15 views
9

Próbuję zrozumieć, jaki jest najlepszy sposób użycia podczas wywoływania metody asynchronicznej, która aktualizuje mój ViewModel. Teraz, powiedzmy, że mam coś takiego:Najlepszy sposób implementacji asynchronicznej metody "loadData" przy użyciu wzorca MVVM

Widok:

private async void NavigationHelper_LoadState(object sender, LoadStateEventArgs e) 
{ 
    //Call my ViewModel method to update the data the UI is bound to   
} 

ViewModel:

public async Task loadData() 
{ 
    this.Source = await loadStuffFromDatabaseAsync(); 
} 

Teraz nie jestem pewien których jeden z następujących podejść powinienem użyć:

1) W mojej metody LoadState, użyj:

await Task.Run(async() => { await ViewMode.loadData(); }); 

2) Zastosowanie Task.Run bez oczekiwania na loaddata metodę wewnątrz działaniu :

await Task.Run(() => { ViewModel.loadData(); }); 

3) połączeń moja metoda loadData za pomocą:

await ViewModel.loadData().ConfigureAwait(false); 

4) Wywołać loaddata metoda bez oczekiwania w moim View klasy i używać Task.Run wewnątrz mojej metody loaddata:

View:

private void NavigationHelper_LoadState(object sender, LoadStateEventArgs e) 
{ 
    ViewModel.loadData(); 
} 

Wyświetl Model:

public async void loadData() 
{ 
    await Task.Run(async() => 
    { 
     this.Source = await loadStuffFromDatabaseAsync(); 
    }); 
} 

Jakie są główne różnice między tymi założeniami?

Czy jeden jest bardziej wydajny niż drugi i czy powinienem go wybrać?

Dzięki za pomoc! :)

Sergio

+0

asynchroniczny void metod i należy postępować zgodnie z konwencją nazewnictwa dołączania ASYNC do wszystkich metod asynchronicznych. –

+0

Wierzę, że Reed Cosby nauczył nas wszystkich, że wszystko, czego potrzebujemy teraz, ponieważ wsparcie Asynch zostało zintegrowane z kodem podstawowym to dwa słowa Async and Await. Nie musimy już wywoływać metod zadań. –

+2

@JohnPeters: To nie prawda. Może istnieć kod blokujący wątek interfejsu użytkownika. – Fred

Odpowiedz

2

Należy używać tylko Task.Run jeśli masz CPU związany lub blokując prace, które chcesz przenieść poza wątku UI. Tak nie jest w tym przypadku, więc bezpośrednie połączenie (opcja 3) jest najbardziej naturalne.

Biorąc je kolejno:

await Task.Run(async() => { await ViewMode.loadData(); }); 

Ta opcja wykona loadData na wątku puli wątków. To może nie działać bardzo dobrze, ponieważ loadData aktualizuje interfejs użytkownika (pośrednio ustawiając właściwość maszyny wirtualnej). Nawet jeśli zadziała (tzn.niektóre środowiska MVVM mogą prawidłowo obsłużyć aktualizacje z wątków działających w tle w niektórych scenariuszach), prawdopodobnie nie jest to konieczne, ponieważ loadData jest metodą asynchroniczną.

Co więcej, dodaje on stan maszyny maszyny bez powodu.

await Task.Run(() => { ViewModel.loadData(); }); 

Opcja ta ma te same problemy, oprócz tego, że jest nieco bardziej wydajny, ponieważ nie posiada maszynę narzut async państwa. Ale wciąż aktualizuje właściwości maszyny wirtualnej na wątku w tle i niepotrzebnie używa wątku tła.

public async void loadData() 

Ten jest najgorszy ze wszystkich. Dziedziczy on te same problemy z innymi: aktualizowanie właściwości VM na wątku tła i używanie niepotrzebnego wątku tła. Do tego dodaje problemy z async void. Jednym z problemów jest to, że NavigationHelper_LoadState nie może wychwycić żadnych wyjątków od loadData. Kolejny problem polega na tym, że loadData nie jest łatwy do sprawdzenia.

więc wystarczy użyć prostego podejścia i nazywają go bezpośrednio: Należy unikać

await ViewModel.loadData().ConfigureAwait(false); 
+0

Dzięki za odpowiedź! Mam tylko wątpliwości: powiedziałeś, że powinienem użyć Task.Run tylko do pracy związanej z CPU lub blokowania: dlaczego ładowanie danych z bazy danych nie jest liczone jako praca blokująca? Ponieważ jest to operacja IO, czy jej ukończenie nie zajmie dużo czasu, a zatem blokuje metodę wywoływania, która oczekuje na to zadanie? – Sergio0694

+1

Wątek nie jest blokowany, ponieważ jest to operacja asynchroniczna. –

+0

Masz rację, przez "blokowanie pracy" rozumiesz, że musisz uruchomić jakiś kod synchroniczny. Jeszcze raz dziękuję za pomoc :) – Sergio0694

Powiązane problemy