任何异步操作都应该加上延迟吗?

8
根据Likness在《使用C#和XAML构建Windows 8应用》一书中的说法(第164页),"在执行异步任务时,必须请求延迟。"
因此,如果我没有将他的话断章取义,那么这段代码:
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");
}

应该改为这样:

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?

1个回答

12
记住,当一个async方法遇到await并且必须(异步)等待时,返回
当你从一个必须在返回之前完成的async void方法中await一个操作时,你需要使用延迟。这种“事件”实际上是一个命令。例如,“鼠标移动”只是一个事件 - 系统不关心你是否处理该事件。但是“挂起”是一个命令 - 系统假定当你从命令返回时,你已经准备好被挂起了。在这种情况下,需要使用延迟来通知系统即使你正在返回,你还没有完成。
类似地,如果你有一个具有Runasync实现的后台任务,你需要使用延迟。因为当Run返回时,你的后台任务被认为已经完成,而你需要一种方式来说明你还没有真正完成。
你可以通过存在GetDeferral方法来判断事件处理程序是否支持此功能。例如,Suspending支持延迟,因为SuspendingEventArgs有一个SuspendingOperation属性,该属性具有一个GetDeferral方法。在后台任务场景中(即,你有一个async void Run),你可以在传递到RunIBackgroundTaskInstance上调用GetDeferral
你提供的SelectAContactForASlot示例返回Task,因此不需要延迟。

只是强调一下Stephen所说的...“必须询问”的上下文是作为命令的一部分,就像Stephen所描述的那样。 - Jeremy Likness

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接