C# 等待异步调用完成
我正在与飞利浦色调,我需要得到一些信息,从色调桥之前,我可以填充我的应用程序。请求是通过HTTP/JSON发出的。当我运行所有代码C# 等待异步调用完成,c#,asynchronous,async-await,win-universal-app,C#,Asynchronous,Async Await,Win Universal App,我正在与飞利浦色调,我需要得到一些信息,从色调桥之前,我可以填充我的应用程序。请求是通过HTTP/JSON发出的。当我运行所有代码async时,我没有问题,但是当我尝试分解代码以便在加载时有一个单独的方法来更新UI时,我在myLights上得到了一个系统。NullReferenceException。我假设这是因为我的startUpProcedure()尚未完成,因此myLights尚未设置。我似乎不知道如何在运行setupUI()之前等待startUpProcedure()完成 为了进一步证实
async
时,我没有问题,但是当我尝试分解代码以便在加载时有一个单独的方法来更新UI时,我在myLights上得到了一个系统。NullReferenceException
。我假设这是因为我的startUpProcedure()
尚未完成,因此myLights尚未设置。我似乎不知道如何在运行setupUI()
之前等待startUpProcedure()
完成
为了进一步证实这一点,如果我只运行startUpProcedure()
,而不运行setupUI()
,我不会遇到任何问题。然后,如果我从一个按钮上运行setupUI()
,单击它就可以正常运行
很明显我遗漏了什么。我就是找不到答案
因此,简明扼要地提出一个问题:如何等待这些异步调用完成,以便使用依赖于其返回值的变量
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;
}
公共密封部分类主页面:第页
{
公共字符串appKey;
公共字符串myIP;
公共照明;
公共ILocalHueClient myClient;
公共主页()
{
this.InitializeComponent();
startUpPocedure();
setupUI();
}
公共异步任务startUpPocedure()
{
等待启动();
等待获取灯光();
}
公共异步任务启动()
{
if(等待findBridgeIP())
{
Debug.WriteLine(“找到桥…”);
//行动
}
其他的
{
//错误!!
Debug.WriteLine(“未找到色调”);
}
Windows.Storage.ApplicationDataContainer localSettings=Windows.Storage.ApplicationData.Current.localSettings;
Windows.Storage.StorageFolder localFolder=Windows.Storage.ApplicationData.Current.localFolder;
试一试{
appKey=localSettings.Values[“appKey”].ToString();
Debug.WriteLine(“加载的appKey:+appKey”);
//装载
myClient=新的LocalHueClient(myIP);
初始化(appKey);
}
抓住{
Debug.WriteLine(“需要注册应用程序”);
}
}
异步任务getLights()
{
myLights=等待myClient.GetLightsAsync();
Debug.WriteLine(“Light Count”+myLights.Count());
IEnumerable mylightname;
List mytemplast=new List();
foreach(myLights中的灯l)
{
myTempList.Add(l.Name);
Debug.WriteLine(l.Name);
}
myLightNames=myTempList;
comboBox_LightSelect.ItemsSource=myLightNames;
}
私有void setupUI()
{
//填充组合框
IEnumerable mylightname;
List mytemplast=new List();
foreach(myLights中的灯l)
{
myTempList.Add(l.Name);
Debug.WriteLine(l.Name);
}
myLightNames=myTempList;
comboBox_LightSelect.ItemsSource=myLightNames;
}
主页构造函数中的startUpPocedure
方法几乎立即返回任务,因为您没有等待它,所以代码执行会立即转到下一行,并调用setupUI
。因此,当您的代码开始枚举myLights
集合时,它仍然为空,因为startUpPocedure
因此,getLights
仍在运行
问题是,您不能在构造函数中等待异步方法,所以在您的情况下,解决方案将是将startUpPocedure
和setupUI
移动到单个异步方法中,在此方法中等待它们,并从构造函数中调用它们,类似于以下内容:
public MainPage()
{
this.InitializeComponent();
Startup();
}
private async void Startup()
{
await startUpPocedure();
setupUI();
}
MainPage构造函数中的
startUpPocedure
方法几乎立即返回任务,因为您没有等待它,所以代码执行会立即转到下一行,并调用setupUI
。因此,当代码开始枚举myLights
集合时,它仍然为空,因为startUpPocedure
因此getLights
仍在运行
问题是,您不能在构造函数中等待异步方法,所以在您的情况下,解决方案将是将startUpPocedure
和setupUI
移动到单个异步方法中,在此方法中等待它们,并从构造函数中调用它们,类似于以下内容:
public MainPage()
{
this.InitializeComponent();
Startup();
}
private async void Startup()
{
await startUpPocedure();
setupUI();
}
您应该只在构造函数中保留
InitializeComponent
,并将所有其他逻辑移动到Loaded
事件处理程序
然后,您可以将该处理程序标记为
async
,并在其中使用await
来等待异步方法。您应该只在构造函数中保留InitializeComponent
,并将所有其他逻辑移到加载的
事件处理程序
然后,您可以将该处理程序标记为async
,并在其中使用await
来等待异步方法