Previously we discussed a way to create a WPF client to consume WCF service.  We’ll now modify the application to consume the service asynchronously, and again in simple steps.

Step 1: Click on the Configure Service Reference… context menu of the service reference and you’ll see the following Service Reference Settings dialog box:

Select the Generate asynchronous operations checkbox and click OK.  If you now view the service reference in object browser, you’ll notice one auto-generated EventArgs subclass for each non-void service operation, in our case it’s GetRegistrationsCompletedEventArgs.  You’ll also notice that the RegistrationServiceClient class has the following additional operations, delegates, and events (… indicates actual service operation name and corresponding parameter) for each actual service API:

  • public event …Completed
  • public Begin…(…, System.AsyncCallback, object)
  • public …Async(…)
  • public …Async(…, object)
  • public End…(System.IAsyncResult)
  • private OnBegin…(object[], System.AsyncCallback, object)
  • private On…Completed(object)
  • private OnEnd…(System.IAsyncResult)
  • private onBegin…Delegate
  • private on…CompletedDelegate
  • private on…Delegate

Replace the existing btnRegister_Click event handler in the code behind with the following code:

private void btnRegister_Click(object sender, RoutedEventArgs e)
{
    RegistrationServiceRef.RegistrationServiceClient client = new RegistrationServiceClient();
    Registration registration = new Registration();
    registration.Registrant = txtRegistrant.Text;
    client.RegisterCompleted += new System.EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(client_RegisterCompleted);
    client.RegisterAsync(registration);
}
void client_RegisterCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
    dgRegistrations.ItemsSource = new RegistrationServiceClient().GetRegistrations();
}

It’s a standard asynchronous model, where you take the following steps:

  1. Setup a callback pointer (wire the event) with a matching target signature
  2. Execute the operation, e.g., …Async(…), in this case
  3. Handle the callback appropriately, e.g., update the display grid in this case

Replace the other two event handlers in the code behind with the code below:

private void btnListRegistrations_Click(object sender, RoutedEventArgs e)
{
    RegistrationServiceRef.RegistrationServiceClient client = new RegistrationServiceClient();
    client.GetRegistrationsCompleted += new System.EventHandler<GetRegistrationsCompletedEventArgs>(client_GetRegistrationsCompleted);
    client.GetRegistrationsAsync();
}
void client_GetRegistrationsCompleted(object sender, GetRegistrationsCompletedEventArgs e)
{
    dgRegistrations.ItemsSource = e.Result;
}

private void btnDeleteRegistration_Click(object sender, RoutedEventArgs e)
{
    RegistrationServiceRef.RegistrationServiceClient client = new RegistrationServiceClient();
    string id = (dgRegistrations.SelectedValue as Registration).Id;
    if (!string.IsNullOrEmpty(id))
    {
        client.DeleteRegistrationCompleted += new System.EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(client_DeleteRegistrationCompleted);
        client.DeleteRegistrationAsync(id);
    }
}
void client_DeleteRegistrationCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
    dgRegistrations.ItemsSource = new RegistrationServiceClient().GetRegistrations();
}

Notice that where a result is expected (e.g., executing a non-void operation), e.Result returns an appropriately typed object.  That concludes our modification to the previously written WPF application to consume the WCF service asynchronously.  In the next sequel, we’ll modify our WCF service to make it available via REST.