1

在我的 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() 方法来等待数据加载吗?

谢谢

4

4 回答 4

4

因此,我们将从这两种方法开始,它们将您现有的方法从基于事件的模型转换为基于任务的模型。您需要稍微修改它们以符合您的类型,因为我没有足够的信息来完全复制它们,但剩余的更改应该很小:

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;
}
于 2013-06-27T13:57:27.327 回答
0

The problem is, when you execute your LoadData() method, the runtime don't wait to continue the execution of your method. You can simply do a think like this :

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;
}

If you want to use async and await, you can try to work with TaskCompletionSource

于 2013-06-27T13:51:35.443 回答
0

将以上两个变量(private bool _moviesLoaded;private bool _theatersLoaded;)作为属性并将它们设置在完成的事件处理程序中。直到集合被称为使用加载器,当集合被调用时禁用这个加载器,现在你可以使用这个数据来工作了..

于 2013-06-27T13:56:27.290 回答
0

底线是您需要为您的应用程序设计和实现“加载”状态。无论您使用基于事件的异步编程(如您当前的代码)还是async/ ,都是如此await。在加载完成之前,您不应同步阻止 UI。

就个人而言,我喜欢(同步)将所有内容初始化为“正在加载”状态,当异步加载完成时,让它更新视图模型上的数据绑定项。然后视图通过数据绑定转换到“就绪”状态。

于 2013-06-27T13:53:49.903 回答