使用async/await和void方法
本文关键字:void 方法 await async 使用 | 更新日期: 2023-09-27 18:20:04
在我的Windows Phone 8应用程序中,我的文件MainViewModel.cs.中有一个LoadData()方法
此方法从具有实体框架的WCF服务加载数据。。。
然后,在我的页面中,我调用LoadData()
LoadData()方法:
public void LoadData()
{
client.GetMoviesCompleted += new EventHandler<ServiceReference1.GetMoviesCompletedEventArgs>(client_GetMoviesCompleted);
client.GetMoviesAsync();
client.GetTheatersCompleted += new EventHandler<ServiceReference1.GetTheatersCompletedEventArgs>(client_GetTheatersCompleted);
client.GetTheatersAsync();
this.IsDataLoaded = true;
}
使用方法:
private void client_GetMoviesCompleted(object sender, ServiceReference1.GetMoviesCompletedEventArgs e)
{
Movies = e.Result;
}
private void client_GetTheatersCompleted(object sender, ServiceReference1.GetTheatersCompletedEventArgs e)
{
Theaters = e.Result;
}
然后在我的页面中:
App.ViewModel.LoadData();
问题是它不会等到数据被加载。
你能帮我使用Async/Await LoadData()方法等待数据加载吗?
感谢
因此,我们将从这两个方法开始,它们将现有方法从基于事件的模型转换为基于任务的模型。你需要稍微修改它们以符合你的类型,因为我没有足够的信息来完全复制它们,但剩下的变化应该很小:
public static Task<Movie[]> WhenGetMovies(MyClient client)
{
var tcs = new TaskCompletionSource<Movie[]>();
Action<object, Movie[]> handler = null;
handler = (obj, args) =>
{
tcs.SetResult(args.Result);
client.GetMoviesCompleted -= handler;
};
client.GetMoviesCompleted += handler;
client.GetMoviesAsync();
return tcs.Task;
}
public static Task<Theater[]> WhenGetMovies(MyClient client)
{
var tcs = new TaskCompletionSource<Theater[]>();
Action<object, Theater[]> handler = null;
handler = (obj, args) =>
{
tcs.SetResult(args.Result);
client.GetTheatersCompleted -= handler;
};
client.GetTheatersCompleted += handler;
client.GetTheatersAsync();
return tcs.Task;
}
现在,我们可以获得代表这些异步操作完成的任务,加载数据很容易:
public async Task LoadData()
{
var moviesTask = WhenGetMovies(client);
var theatersTask = WhenGetTheaters(client);
var movies = await moviesTask;
var theaters = await theatersTask;
}
问题是,当您执行LoadData()方法时,运行时不会等待继续执行您的方法。你可以简单地这样想:
private bool _moviesLoaded;
private bool _theatersLoaded;
private void client_GetMoviesCompleted(object sender, ServiceReference1.GetMoviesCompletedEventArgs e)
{
Movies = e.Result;
_moviesLoaded = true;
TrySetDataIsLoaded();
}
private void client_GetTheatersCompleted(object sender, ServiceReference1.GetTheatersCompletedEventArgs e)
{
Theaters = e.Result;
_theatersLoaded = true;
TrySetDataIsLoaded();
}
private void TrySetDataIsLoaded()
{
if(_moviesLoaded && _theatersLoaded) this.IsDataLoaded = true;
}
如果您想使用async和wait,可以尝试使用TaskCompletionSource
最重要的是,您需要为应用程序设计和实现一个"加载"状态。无论使用基于事件的异步编程(如当前代码)还是async
/await
,都是如此。在加载完成之前,不应同步阻止UI。
就我个人而言,我喜欢(同步地)将所有内容初始化为"加载"状态,当异步加载完成时,让它更新视图模型上的数据绑定项。然后,视图通过数据绑定转换到"就绪"状态。
将以上两个变量(private bool_viesLoaded;private bool _theaters Loaded;)作为属性,并在已完成的事件处理程序中设置它们。直到集合被调用,使用加载器,当集合被调用时,禁用这个加载器,现在你可以将这些数据用于你的工作。。