等待异步调用完成
我正在使用飞利浦Hue,我需要从色相桥获取一些信息才能填充我的应用程序。请求通过HTTP/JSON进行。当我运行我所有的代码async
时,我没有任何问题,但是当我尝试分解我的代码以便在加载时有一个单独的方法来更新UI时,我在myLights上获得了System.NullReferenceException
。我假设这是因为我的startUpProcedure()
尚未完成,因此myLights尚未设置。在运行setupUI()
之前,我似乎无法弄清楚如何等待startUpProcedure()
完成。等待异步调用完成
为了进一步说明这一点,如果我只是在没有setupUI()
的情况下运行startUpProcedure()
,则不会出现问题。然后,如果我运行setupUI()
从说按钮点击它运行得很好。
显然我在这里错过了一些东西。我似乎无法找到答案。
所以要简洁地提出这个问题:如何等待这些Async调用完成,以便可以使用依赖于它们的返回值的变量?
public sealed partial class MainPage : Page
{
public string appKey;
public string myIP;
public IEnumerable<Light> myLights;
public ILocalHueClient myClient;
public MainPage()
{
this.InitializeComponent();
startUpPocedure();
setupUI();
}
public async Task startUpPocedure()
{
await startUp();
await getLights();
}
public async Task startUp()
{
if (await findBridgeIP())
{
Debug.WriteLine("Bridge Found...");
//Do Actions
}
else
{
//Error!!
Debug.WriteLine("No hue found");
}
Windows.Storage.ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
Windows.Storage.StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
try {
appKey = localSettings.Values["appKey"].ToString();
Debug.WriteLine("appKey loaded: " + appKey);
//Load up
myClient = new LocalHueClient(myIP);
myClient.Initialize(appKey);
}
catch {
Debug.WriteLine("Need to register app");
}
}
async Task getLights()
{
myLights = await myClient.GetLightsAsync();
Debug.WriteLine("Light Count " + myLights.Count());
IEnumerable<string> myLightNames;
List<string> myTempList = new List<string>();
foreach (Light l in myLights)
{
myTempList.Add(l.Name);
Debug.WriteLine(l.Name);
}
myLightNames = myTempList;
comboBox_LightSelect.ItemsSource = myLightNames;
}
private void setupUI()
{
//Populate the Combo Box
IEnumerable<string> myLightNames;
List<string> myTempList = new List<string>();
foreach (Light l in myLights)
{
myTempList.Add(l.Name);
Debug.WriteLine(l.Name);
}
myLightNames = myTempList;
comboBox_LightSelect.ItemsSource = myLightNames;
}
你startUpPocedure
在构造函数中的MainPage方法几乎立即返回的任务,因为你不等待它,代码执行后立即行进至下一行,setupUI
被调用。因此,当您的代码开始枚举myLights
集合时,它仍然为空,因为startUpPocedure
因此getLights
仍在运行。
问题是,你不能等待异步方法在一个构造函数,所以你的情况的解决方案将是既startUpPocedure
和setupUI
移动到单一异步方法,等待他们这种方法中,并从类似这样的构造函数中调用它:
public MainPage()
{
this.InitializeComponent();
Startup();
}
private async void Startup()
{
await startUpPocedure();
setupUI();
}
你应该只留下InitializeComponent
在构造函数中,并将所有其他逻辑Loaded
事件处理程序,
https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.frameworkelement.loaded
然后,您可以将该处理程序标记为async
,并使用其中的await
来等待异步方法。