簡體   English   中英

使用async / await和void方法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM