Home > OS >  Async OnStartup in a WPF application
Async OnStartup in a WPF application

Time:09-15

I have a WPF application. If it is started with some command line parameter, it should only do some database operations and then close itself. This is done in the App.xaml.cs:

public partial class App : Application
{
  protected override async void OnStartup(StartupEventArgs e)
  {
    base.OnStartup(e);
    if(Environment.GetCommandLineArgs().Any(x => x == "blabla"))
    {
      await PerformDatabaseOperations()
      Environment.Exit(0);   
    }
    
    var mainWindow = new MainWindow();
    mainWindow.Show();
    this.MainWindow = mainWindow;
  }
}

The problem with this code is that the method PerformDatabaseOperations() is not executed completely. The moment it hits the first actual database operation, the program exits. I assume this is because OnStartup doesn't return a Task and thus can't be awaited. Because of this, the line Environment.Exit(0); is executed when the first asynchronous operation is encountered inside this method.

Is there a way to fix this?

CodePudding user response:

You can call async Methods from within a synchronous method like this:

YourAsyncMethod().Wait();

So you can make your OnStartup-Method synchronous and perform your database operations like this:

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    if(Environment.GetCommandLineArgs().Any(x => x == "blabla"))
    {
        PerformDatabaseOperations().Wait();
        Environment.Exit(0);   
    }

    var mainWindow = new MainWindow();
    mainWindow.Show();
    this.MainWindow = mainWindow;
}

CodePudding user response:

From the point of view of the application, your OnStartup method returns when the first await is hit. At that point it has not created or shown any windows.

My guess is that this causes the application to terminate since there is no message loop started. You could check your theory placing a breakpoint on the Environment.Exit(0), my guess is that this will not be hit.

Creating the mainWindow before doing your database operation might solve the issue, but will result in a empty window being shown, but I'm not sure if there is any good workaround for that problem. When creating a similar application I went the other way, using a console program that shows a UI window, leaving a console box in addition to the UI.

Note that you should be very careful to handle any exception when using async void, since these will otherwise be lost.

  • Related