4

Good afternoon. I am currently building an app with .Net Maui and .Net Framework 7.0 for Android and iOS (currently using the Pixel 5 Android Emulator), which should automatically do some stuff (such as authentication) on startup and then redirect the user accordingly to the corresponding page.

In my startpage (StartPage.xaml.cs) I am calling the initialization method from the viewmodel as follows:

protected override async void OnAppearing()
        => await _ViewModel.InitializeAsync();

While the initialization-code in the viewmodel looks like this:

public async Task InitializeAsync()
{
    // ATTENTION: IF THE NEXT LINE IS COMMENTED OUT, EVERYTHING WORKS FINE.
    // HOWEVER, INSTEAD OF THE DELAY THIS IS THE PLACE I WOULD LIKE TO INITIALIZE THE APP (CALL SERVER, AUTHENTICATE ETC).
    await Task.Delay(1000);

    var user = new User();
    var parameters = NavigationService.GetParamsForObject(Tuple.Create("User", (object)user));

    // Go to the main page
    await NavigationService.GoToMainPage(parameters, true);
          
}

The app seems to start up correctly and the user gets redirected to the "main"-page as expected. However, as mentioned in the comment of the code-snippet above, the line "await Task.Delay(1000)" (where my actual initialization-logic would take place) causes a TaskCancelledException in the redirected MainPage (where a Map-Control with Custom-pins is loaded). If I comment out the line "await Task.Delay(1000)" everything works as expected.

Whats the problem with using an await-Statement in the InitializeAsync-Method? Am I missing something? Or is this just the wrong place to (automatically) initialize the app? I dont want the user to click on a button first, the initialization should take place automatically.

Thank you very much for your help.

I tried:

  • MainThread.InvokeOnMainThread() to run the initialization-logic
  • Using a Dispatcher
  • Catch the TaskCancelledException, but this leads to unexpected behaviour
  • Override OnNavigatedFrom instead of OnAppearing
cyrill
  • 53
  • 1
  • 5
  • You can refer to this [case](https://stackoverflow.com/questions/15181855/why-does-taskcanceledexception-occur), it talks about TaskCancelledException in details. It could be helpful to you. – Jianwei Sun - MSFT Nov 21 '22 at 02:38

2 Answers2

3

You can't do asynchronous work before showing your initial UI. You'll need to start the asynchronous work and then (immediately and synchronously) display a UI of some kind (e.g., a "Loading..." screen). Then, when your asynchronous work completes, update/replace the Loading UI with your actual Main UI.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
1

The loading function is best to be placed as a Task into App.xaml.cs. At the end of the time consuming function raise an event (eg Download Completed).

public App()
{
        InitializeComponent();

        Task.Run(async () =>
        {
            Console.WriteLine("wait for 10secs");
            await Task.Delay(10000);
            //await DownloadData();
            Console.WriteLine("completed");
            WeakReferenceMessenger.Default.Send("DOWNLOAD COMPLETED");

        });

        MainPage = new AppShell();
    }
}

and catch the event by registering the reference to your StartPage.xaml.cs.

WeakReferenceMessenger.Default.Register<string>(this, (r, m) =>
  {
      Console.WriteLine($"EVENT {m}");
      if (m == "DOWNLOAD COMPLETED")
      {
          //notify user
      }

   });
Isidoros Moulas
  • 520
  • 3
  • 10