2015-02-23 12 views
9

Ich versuche zu verstehen, welche Methode beim Aufrufen einer asynchronen Methode, die mein ViewModel aktualisiert, am besten ist. Gerade jetzt, sagen wir, ich so etwas wie dieses:Die beste Methode zum Implementieren einer asynchronen "loadData" -Methode mit dem MVVM-Muster

Ausblick:

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

Ansichtsmodell:

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

Nun, ich bin nicht sicher, ob das eine der folgenden Ansätze sollte ich verwenden:

1) In meiner Loadstate-Methode verwenden:

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

2) Verwenden Task.Run ohne die loaddata Methode innerhalb der Aktion zu warten:

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

3) Anruf meine loadData Methode mit:

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

4) Rufen Sie die loaddata Methode ohne es in meinem View-Klasse wartet und Task.Run in meinem loaddata-Methode verwenden:

Ausblick:

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

Ansicht Modell:

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

Was sind die wichtigsten Unterschiede zwischen diesen approaces sind?

Ist eine mehr effizient als die andere, und sollte ich eine speziell auswählen?

Danke für Ihre Hilfe! :)

Sergio

+0

async Leere Methoden sollten vermieden werden, und Sie sollten die Namenskonvention von Anhängen Async auf alle Asynchron-Methoden folgen. –

+0

Ich glaube, dass Reed Cosby uns alles gelehrt hat, dass alles, was wir jetzt brauchen, seit Asynch Unterstützung in den Basiscode integriert wurde, zwei Wörter Async und Await ist. Wir müssen die Task-Methoden nicht mehr aufrufen. –

+2

@JohnPeters: Das ist nicht wahr. Möglicherweise gibt es Code, der den UInthread blockiert. – Fred

Antwort

2

Sie nur Task.Run verwenden sollten, wenn Sie CPU-gebunden haben oder Blockierung der Arbeit, die Sie den UI-Thread losfahren wollen. Das ist hier nicht der Fall, also ist der direkte Anruf (Option 3) der natürlichste.

Unter ihnen wiederum:

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

Diese Option loadData auf einem Thread-Pool-Thread ausgeführt wird. Dies funktioniert möglicherweise nicht sehr gut, da loadData die Benutzeroberfläche aktualisiert (indirekt durch Festlegen einer VM-Eigenschaft). Selbst wenn es funktioniert (d. H., einige MVVM-Frameworks können in bestimmten Szenarien Aktualisierungen von Hintergrundthreads ordnungsgemäß verarbeiten), ist wahrscheinlich unnötig, da loadData eine asynchrone Methode ist.

Darüber hinaus hinzugefügt async State Machine Overhead ohne Grund.

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

Diese Option hat die gleichen Probleme, außer es etwas effizienter ist, da es nicht den Overhead async Zustandsmaschine hat. Aber es aktualisiert weiterhin VM-Eigenschaften in einem Hintergrund-Thread und verwendet unnötigerweise einen Hintergrund-Thread.

public async void loadData() 

Dies ist das Schlimmste von allen. Es erbt dieselben Probleme wie die anderen: Aktualisieren der VM-Eigenschaften in einem Hintergrund-Thread und Verwenden eines unnötigen Hintergrund-Threads. Dazu kommen die Probleme von async void hinzu. Ein Problem ist, dass NavigationHelper_LoadState keine Ausnahmen von loadData abfangen kann. Ein weiteres Problem ist, dass loadData nicht leicht testbar ist.

So benutzen Sie einfach den einfachen Ansatz und nennen es direkt:

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

Danke für Ihre Antwort! Ich habe nur Zweifel: Sie sagten, ich sollte Task.Run nur für CPU-gebundene oder blockierende Arbeit verwenden: Warum zählt das Laden von Daten aus einer Datenbank nicht als Blockierung? Da es sich um eine IO-Operation handelt, kann das nicht lange dauern und daher die aufrufende Methode, die auf diese Task wartet, blockieren? – Sergio0694

+1

Der Thread wird nicht blockiert, da es sich um eine asynchrone Operation handelt. –

+0

Sie haben recht, wenn Sie "Arbeit blockieren" meinten, wollten Sie einen synchronen Code ausführen. Danke nochmal für deine Hilfe :) – Sergio0694

Verwandte Themen