[英]Using async/await with void method
在我的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和await,可以嘗試使用TaskCompletionSource
最重要的是,您需要為您的應用程序設計並實現“加載”狀態。 無論您使用基於事件的異步編程(如當前代碼)還是async
/ await
。 你不應該同步阻止用戶界面,直到加載完成。
就個人而言,我喜歡(同步)將所有內容初始化為“加載”狀態,並且當異步加載完成時,讓它更新視圖模型上的數據綁定項。 然后,View通過數據綁定轉換為“就緒”狀態。
將兩個變量(private bool _moviesLoaded; private bool _theatersLoaded;)作為屬性並在完成的事件處理程序中設置它們。 直到該集合被稱為使用加載器並且當調用set時禁用此加載器,現在您可以將此數據用於您的工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.