2016-08-07 48 views
-1

Rückkehr Nach einigen ausgezeichneten Hilfe in a similar question I asked recently und ein ähnliches Beispiel in this SO answer gezeigt, habe ich versucht, diese auf einen Befehl in einem MVVM Ansicht Modell anzuwenden wie folgt ...async MVVM Befehl sofort

private async void BookAppointmentCommandExecute() { 
    Debug.WriteLine("VM Start"); 
    IsBusy = true; 
    await Task.Run(() => Service.BookAppointment(Appointment.ID, PatientID)); 
    IsBusy = false; 
    Debug.WriteLine("VM Done"); 
} 

Die WCF Service-Aufruf sieht wie folgt aus ...

[OperationContract] 
public void BookAppointment(int appointmentID, int patientID) { 
    Debug.WriteLine("Svc Start"); 
    Task.Delay(1000); 
    AppointmentsServiceLogic.BookAppointment(appointmentID, patientID); 
    Debug.WriteLine("Svc Done"); 
} 

die Task.Delay wurde hinzugefügt Netzwerklatenz zu simulieren, so kann ich überprüfen, ob die Betriebsanzeige auf der Ansicht korrekt angezeigt wird. Es war nicht.

In beiden Fällen wurden die Debug.WriteLine Anweisungen hinzugefügt, um mir zu helfen, zu sehen, was vor sich ging.

Im Gegensatz zu den beiden Beispielen, die ich verlinkt habe, unterbricht mein Code die Ausführung in der await Zeile der Befehlsmethode nicht, sondern setzt stattdessen sofort fort. Aus den Ergebnissen im Ausgabefenster, kann ich die Verzögerung verursacht sehen durch die Task.Delay geschieht nach der Befehl Methode Ausführung beendet hat ...

40:30:409 VM Start 
40:30:409 Svc Start 
40:30:409 VM Done 
40:31:410 Svc Done 

Wie Sie den Befehl Methode sofort beendet sehen können, dann gibt war eine Sekunde Verzögerung (nachdem IsBusy auf false zurückgesetzt wurde), und erst dann kehrte die Service-Methode zurück. Ich dachte, die Idee war, dass die Ausführung der Befehlsmethode ausgesetzt wurde, bis die awaited ed-Methode abgeschlossen war.

Kann jemand erklären, was ich falsch mache?

+0

Verwenden Thread.Sleep statt Task.Delay Lage –

+0

Jeder würde sagen würde, warum dies auf Eis gelegt wurde, zu erklären? Wenn ich den angegebenen Grund ansehe, scheint es, dass ich das gewünschte Verhalten nicht berücksichtigt habe. Hmm, ich sagte '... damit ich überprüfen kann, ob die Besetztanzeige in der Ansicht korrekt angezeigt wird. Es schien mir nicht eine ziemlich klare Beschreibung des Problems zu sein. Außerdem habe ich die beiden einzigen relevanten Methoden einbezogen, so dass das Problem aus dem angegebenen Code reproduzierbar ist. Was war nicht am Thema? Ich versuche nicht, einen Streit anzufangen, ich möchte wissen, wie ich meine Fragen verbessern kann. –

+0

Es scheint mir, dass der nahe Grund Banner ziemlich klar ist: Sie haben versäumt, eine gute [MCVE] bereitzustellen, die Ihr Problem zuverlässig reproduziert.Das macht Ihre Frage zum Thema, egal wie gut jemand bei _guessing_ ist, was das Problem ist. –

Antwort

1

Sie scheinen ein Missverständnis darüber zu haben, wie async-await funktioniert. Schauen Sie sich die Blog von Stephen Cleary für eine Einführung: http://blog.stephencleary.com/2012/02/async-and-await.html

Einige schnelle Beispielcode veranschaulichen das Problem:

Debug.WriteLine("Start"); 
await MyAsyncTask(); 
Debug.WriteLine("End"); 

Das await Schlüsselwort führt die Aufgabe folgenden es (so dass die Methode MyAsyncTask) auszuführen asynchron, aber wartet auf sie, bevor sie fortfahren Ausführung zu beenden (was bedeutet „End“ auf der Konsole ausgegeben, nachdem MyAsyncTask fertig exceution)

Ein weiteres Beispiel:

Debug.WriteLine("Start"); 
MyAsyncTask(); 
Debug.WriteLine("End"); 

Jetzt wird "End" in die Konsole geschrieben, sofort nachdem MyAsyncTask gestartet wurde, also vor seiner Fertigstellung.

auf Ihr spezielles Beispiel Angewandt ich eine Möglichkeit, dies zu tun

private async void BookAppointmentCommandExecute() { 
    Debug.WriteLine("VM Start"); 
    IsBusy = true; 
    await Service.BookAppointment(Appointment.ID, PatientID); //as I've changed the return type of the method below, I can now directly await it 
    IsBusy = false; 
    Debug.WriteLine("VM Done"); 
} 

//the method should return Task, so you can use the await keyword to wait for its completion 
//I've marked the method with the async keyword so I can use the await keyword within 
[OperationContract] 
public async Task BookAppointment(int appointmentID, int patientID) { 
    Debug.WriteLine("Svc Start"); 
    await Task.Delay(1000); 
    //(depending if AppointmentsServiceLogic.BookAppointment is implemented asynchronous) 
    await AppointmentsServiceLogic.BookAppointment(appointmentID, patientID); 
    //or 
    await Task.Run(() => AppointmentsServiceLogic.BookAppointment(appointmentID, patientID)); 
    Debug.WriteLine("Svc Done"); 
} 
+0

Ich gebe zu, es nicht zu verstehen! Ich habe diesen Blog gelesen und neu gelesen und habe immer noch Probleme damit, mich darum zu kümmern, weshalb ich hier gefragt habe. Jedenfalls habe ich deinen Vorschlag ausprobiert, aber es hat nicht geholfen. Ich habe den Service-Anruf wie von Ihnen vorgeschlagen asynchron ausgeführt und die Service-Referenz in der Client-App aktualisiert. Die VM-Methode wurde jedoch beendet, bevor die Service-Methode zurückgegeben wurde. Irgendwelche Ideen? Danke –

+0

Können Sie den Debugger auf beiden Seiten verwenden, um zu sehen, was vor sich geht? Sind Sie sicher, dass Sie auf den Anruf warten? –