According to Likness (p. 164, “Building Windows 8 Apps with C# and XAML”), “When performing asynchronous tasks, you must ask for a deferral.”
So if I’m not taking him out of context, this code:
private async Task<System.Collections.Generic.KeyValuePair<string, string>> SelectAContactForASlot()
{
KeyValuePair<string, string> kvp;
var contactPicker = new Windows.ApplicationModel.Contacts.ContactPicker();
contactPicker.CommitButtonText = "Select";
var contact = await contactPicker.PickSingleContactAsync();
if (contact != null)
{
kvp = new KeyValuePair<string, string>(contact.Name, contact.Emails[0].ToString());
return kvp;
}
return kvp = new KeyValuePair<string, string>("No Name found", "No email found");
}
…should be this instead:
private async Task<System.Collections.Generic.KeyValuePair<string, string>> SelectAContactForASlot()
{
var deferral = e.SuspendingOperation.GetDeferral();
KeyValuePair<string, string> kvp;
var contactPicker = new Windows.ApplicationModel.Contacts.ContactPicker();
contactPicker.CommitButtonText = "Select";
var contact = await contactPicker.PickSingleContactAsync();
if (contact != null)
{
kvp = new KeyValuePair<string, string>(contact.Name, contact.Emails[0].ToString());
return kvp;
}
return kvp = new KeyValuePair<string, string>("No Name found", "No email found");
deferral.Complete();
}
Correct?
Remember that an
asyncmethod returns when it hits anawaitand has to (asynchronously) wait.You need a deferral when you
awaitan operation from anasync voidmethod that must complete before it returns. This kind of “event” is really a command. E.g., “the mouse moved” is just an event – the system doesn’t care whether or not you handle the event. But “suspend” is a command – the system assumes that when you return from the command, you are done getting ready to be suspended. In this case, deferrals are necessary to inform the system that even though you’re returning, you’re not done yet.Similarly, you need a deferral if you have a background task that has an
asyncimplementation ofRun. Because whenRunreturns, your background task is considered done, and you need a way to say you’re not really done yet.You can tell if an event handler supports this by the presence of a
GetDeferralmethod. For example,Suspendingsupports deferral becauseSuspendingEventArgshas aSuspendingOperationproperty which has aGetDeferralmethod. In the background task scenario (i.e., you have anasync void Run), you can callGetDeferralon theIBackgroundTaskInstancepassed intoRun.Your example of
SelectAContactForASlotreturnsTask, so it doesn’t need the deferral.