立即返回异步MVVM命令

时间:2016-08-07 21:53:12

标签: c# asynchronous mvvm async-await

a similar question I asked recently中有一些很好的帮助,以及this SO answer中显示的类似示例之后,我尝试将其应用于MVVM视图模型中的命令,如下所示......

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

WCF服务调用如下所示......

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

添加了Task.Delay来模拟网络延迟,因此我可以检查视图上的忙指示是否正确显示。事实并非如此。

在这两种情况下,添加了Debug.WriteLine语句以帮助我了解发生了什么。

与我链接的两个示例不同,我的代码不会在命令方法中的await行暂停执行,而是立即执行。从“输出”窗口中的结果中,我可以看到Task.Delay在命令方法执行完毕后发生的引起的延迟......

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

正如您所看到的,命令方法立即完成,然后有一秒钟的延迟(在IsBusy被设置回false之后),然后才返回服务方法。我认为这个想法是命令方法的执行被暂停,直到awaited ed方法完成。

任何人都能解释我做错了什么?

1 个答案:

答案 0 :(得分:1)

您似乎对async-await的工作方式存在误解。查看Stephen Cleary的博客作为介绍:http://blog.stephencleary.com/2012/02/async-and-await.html

一些快速示例代码来说明您的问题:

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

await关键字执行后面的任务(所以方法MyAsyncTask)执行异步,但在继续执行之前等待它完成(这意味着"结束"是MyAsyncTask完成优惠后打印到控制台

另一个例子:

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

现在"结束"在MyAsyncTask启动后立即写入控制台,因此在完成之前。

应用于您的具体示例我说要做到这一点的方法是

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");
}