user3841581
user3841581

Reputation: 2747

How to wait for a Navigation.PushAsync() task to complete before continue executing

I have the following code:

 Task task = Navigation.PushAsync(myPage);
 foreach(var temp in myModel)
 {

      //do bla bla
 }

On the page I called, when I am done executing what I need, I do this:

this.Navigation.PopAsync();

The problem is I would like to execute my for loop only after my task has completed executing or after my myPage has completed executing.

How can I tackle this?

Upvotes: 4

Views: 4063

Answers (3)

Damien Doumer
Damien Doumer

Reputation: 2265

You can do this by calling an event from the page's OnDisapearing method, this event can then be subscribed by the navigation service which you create, and you can then use the "TaskCompletionSource" to wati until your page finishes its work and then complete the task. For more details about accomplishing this, you can check this blog post.

Here is an overview of the navigation service you should use:

public async Task<T> NavigateToModal<T>(string modalName)
    {
        var source = new TaskCompletionSource<T>();
        if (modalName == nameof(NewItemPage))
        {
            var page = new NewItemPage();
            page.PageDisapearing += (result) =>
            {
                var res = (T)Convert.ChangeType(result, typeof(T));
                source.SetResult(res);
            };
            await App.Current.MainPage.Navigation.PushModalAsync(new NavigationPage(page));
        }
        return await source.Task;
    }

Upvotes: 1

Rafael
Rafael

Reputation: 108

If I got you right, you want that the foreach loop is executed after this.Navigation.PopAsync() has been executed. Right?

I would propose one of the following approaches:

1) Do the task on (pushed) myPage's when it get's it PopAsync(): You could hand over whatever data (e.g. myModel) you need in an object to myPage and execute the loop in

protected override void OnDisappearing()
{
    base.OnDisappearing();
    foreach(var temp in myModel)
    {
         //do bla bla
    }
}

2) You set a flag on your original page that it has been hidden by the pushAsync(myPage) and deal execute your code after reappearing.

bool pushStarted;

protected void YourMethod()
{
    pushStarted = true;
    await Navigation.PushAsync(myPage);
}

protected override void OnAppearing()
{
    base.OnAppearing();
    if(pushStarted)
    {
        pushStarted = false;
        foreach(var temp in myModel)
        {
             //do bla bla
        }
    }
}

Upvotes: 1

Babak Naffas
Babak Naffas

Reputation: 12561

Assuming you are in an async method, you can change your implementation to

await Navigation.PushAsync(myPage)

then continue with your for loop.

If you are not in an async method, you can call the method and force a blocking wait by calling GetAwaiter().GetResult();

Navigation.PushAsync(myPage).GetAwaiter().GetResult();

Upvotes: 4

Related Questions