简体   繁体   中英

Using async/await with void method

in my Windows Phone 8 application, I have a LoadData() method in my file MainViewModel.cs.

This method load data from a WCF service with entity framework...

Then, in my pages, I call LoadData()

The LoadData() method :

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

With the methods :

private void client_GetMoviesCompleted(object sender, ServiceReference1.GetMoviesCompletedEventArgs e)
{
    Movies = e.Result;
}

private void client_GetTheatersCompleted(object sender, ServiceReference1.GetTheatersCompletedEventArgs e)
{
    Theaters = e.Result;
}

Then in my pages :

 App.ViewModel.LoadData();

The problem is that it doesn't wait until the data is loaded.

Can you help me to use Async/Await the LoadData() method to wait until the data is loaded ?

Thanks

So we'll start with these two methods that convert your existing methods from an event-based model into a task based model. You'll need to modify them slightly to line up with your types as I don't quite have enough information to replicate them completely, but the remaining change should be small:

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

Now that we can get tasks that represent the completion of these async operations loading the data is easy:

public async Task LoadData()
{
    var moviesTask = WhenGetMovies(client);
    var theatersTask = WhenGetTheaters(client);
    var movies = await moviesTask;
    var theaters = await theatersTask;
}

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

The bottom line is that you'll need to design and implement a "loading" state for your application. This is true whether you use event-based asynchronous programming (like your current code) or async / await . You should not synchronously block the UI until the loading is complete.

Personally, I like to (synchronously) initialize everything into the "loading" state, and when the asynchronous loading completes, have it update data-bound items on the View Model. The View then transitions to a "ready" state via data binding.

make above two variables (private bool _moviesLoaded;private bool _theatersLoaded;) as properties and set them in completed eventhandlers . and till the set is called use loader and when set is called disable this loader and now you can use this data for your work..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM