【发布时间】:2012-11-22 18:01:15
【问题描述】:
我现在对显示为 I was having 的人员/联系人没有任何问题 - 现在它们已经连续显示了好几次 - 但是检索联系人对象的调用永远不会返回 - 断点位于此行:
var contact = await contactPicker.PickSingleContactAsync();
...我从来没有到达那里-尽管我可以选择一个联系人,然后选择“选择”按钮。控制永远不会从模拟器切换到断点。
为了全面披露,这里是整个方法:
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].Value);
if (null != kvp.Value) // If there is no email, there's no use in passing it back, as the person cannot be contacted
{
return kvp;
}
else
{
return kvp = new KeyValuePair<string, string>(contact.Name, "No email found");
}
}
return kvp = new KeyValuePair<string, string>("No Name found", "No email found");
}
那么为什么对 PickSingleContactAsync() 的调用永远不会返回?
更新
某个功能的所有按钮共享一个 OnClick 处理程序(我应该进入 21.08 世纪并使用 OnTapped 处理程序);这个处理程序像这样调用异步方法:
Task<System.Collections.Generic.KeyValuePair<string, string>> kvpContactNameEmail = SelectAContactForASlot();
更新 2
好吧,现在我真的被迷住了:
这段代码,在按钮Onclick中:
private void PersonButton_OnClick(object sender, RoutedEventArgs args)
{
Task<System.Collections.Generic.KeyValuePair<string, string>> kvpContactNameEmail = SelectAContactForASlot();
Button btn = null;
if (args.OriginalSource is Button)
{
btn = args.OriginalSource as Button;
}
if (null == btn)
{
return;
}
//btn1_1 to btn3_4
if (btn.Name == "btn1_1")
{
ApplicationData.Current.LocalSettings.Values["PersonSection1Slot1"] = kvpContactNameEmail.Result.Key;
btn1_1.Foreground = new SolidColorBrush(Windows.UI.Colors.Gray);
. . .
...确实通过了对 SelectAContactForASlot() 的调用——单步执行第一行会立即返回——但它会在人员/联系人选择器显示之前返回。因此,KVP 中没有键或值,因为它返回的 SelectAContactForASlot() 应该返回:
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>("No Name found", "No email found");
}
else // contact != null
{
if (string.IsNullOrWhiteSpace(contact.Emails[0].Value))
{
kvp = new KeyValuePair<string, string>(contact.Name, "No email found");
}
else
{
kvp = new KeyValuePair<string, string>(contact.Name, contact.Emails[0].Value);
}
}
return kvp;
}
...由于某种原因,人员/联系人选择器会在到达此行时显示(假设我单击了 btn1_1):
ApplicationData.Current.LocalSettings.Values["PersonSection1Slot1"] = kvpContactNameEmail.Result.Key;
...但是,实际上没有返回任何内容,因为它停止在线:
var contactPicker = new Windows.ApplicationModel.Contacts.ContactPicker();
所以 SelectAContactForASlot() 被调用的时间比我认为它应该/应该的要晚,但是一旦它被调用,它就无法继续。
更新 3
private void PersonButton_OnClick(object sender, RoutedEventArgs args)
{
Task<System.Collections.Generic.KeyValuePair<string, string>> kvpContactNameEmail = SelectAContactForASlot();
. . .
private async Task<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>("No Name found", "No email found");
}
else // contact != null
{
if (string.IsNullOrWhiteSpace(contact.Emails[0].Value))
{
kvp = new KeyValuePair<string, string>(contact.Name, "No email found");
}
else
{
kvp = new KeyValuePair<string, string>(contact.Name, contact.Emails[0].Value);
}
}
return kvp;
}
更新 4
...如果我将 buttonClick 代码更改为:
private async void PersonButton_OnClick(object sender, RoutedEventArgs args)
{
Task<System.Collections.Generic.KeyValuePair<string, string>> kvpContactNameEmail = await SelectAContactForASlot();
. . .
(在此处添加了“async”和“await”),我得到,“无法将类型 'System.Collections.Generic.KeyValuePair' 隐式转换为 'System.Threading.Tasks.Task>'"
我想我的问题确实是我不希望调用 SelectAContactForASlot() 在检索到联系人对象(调用联系人应用程序并且用户选择联系人)之前返回; IOW,我希望它是异步的。但我认为没有 PickSingleContactAsync() 的异步版本 - IOW,没有“PickSingleContact”。
所以我真正想知道的是:如何调用联系人应用程序并允许用户选择一个联系人(已经这样做)并从该对象中取回我可以在我的代码中访问的值?显然我的想法是错误的。
【问题讨论】:
-
你在等待调用这个方法吗?
-
我想问的是,您是否在某个时候对返回的任务调用 Wait() 方法。如果您从 UI 线程启动此异步操作并且您正在等待任务,则对 contactPicker.PickSingleContactAsync() 的调用的继续将无法执行,因为 UI 线程被阻塞等待。
-
不,我在任何地方都没有 Wait()。
标签: c# windows-8 async-await windows-store-apps peoplepicker