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 async
method returns when it hits an await
and has to (asynchronously) wait.
You need a deferral when you await
an operation from an async void
method 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 async
implementation of Run
. Because when Run
returns, 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 GetDeferral
method. For example, Suspending
supports deferral because SuspendingEventArgs
has a SuspendingOperation
property which has a GetDeferral
method. In the background task scenario (i.e., you have an async void Run
), you can call GetDeferral
on the IBackgroundTaskInstance
passed into Run
.
Your example of SelectAContactForASlot
returns Task
, so it doesn't need the deferral.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With