@@ -76,13 +76,15 @@ public CliApp ConfigureServices(Action<IServiceCollection, IConfiguration> confi
7676 /// <param name="args">Command-line arguments forwarded from <c>Program.cs</c>.</param>
7777 /// <param name="configure">Registers the tool's commands on the Spectre configurator.</param>
7878 /// <returns>The process exit code: 0 on success, 1 on an unhandled exception.</returns>
79- public Task < int > RunAsync ( string [ ] args , Action < IConfigurator > ? configure = null )
79+ public async Task < int > RunAsync ( string [ ] args , Action < IConfigurator > ? configure = null )
8080 {
81- // Build the DI registrar through the shared bootstrap.
81+ // Build the DI registrar through the shared bootstrap. Awaiting before the using disposes it keeps the
82+ // service provider (and its singletons, e.g. the HttpClient meter factory) alive until the async command
83+ // actually finishes.
8284 using var registrar = BuildRegistrar ( ) ;
8385
8486 // Run a command app with no compile-time default command.
85- return CliRunner . RunAsync ( new CommandApp ( registrar ) , args , configure ) ;
87+ return await CliRunner . RunAsync ( new CommandApp ( registrar ) , args , configure ) ;
8688 }
8789
8890 /// <summary>
@@ -93,14 +95,16 @@ public Task<int> RunAsync(string[] args, Action<IConfigurator>? configure = null
9395 /// <param name="args">Command-line arguments forwarded from <c>Program.cs</c>.</param>
9496 /// <param name="configure">Optionally registers additional commands on the Spectre configurator.</param>
9597 /// <returns>The process exit code: 0 on success, 1 on an unhandled exception.</returns>
96- public Task < int > RunAsync < TDefaultCommand > ( string [ ] args , Action < IConfigurator > ? configure = null )
98+ public async Task < int > RunAsync < TDefaultCommand > ( string [ ] args , Action < IConfigurator > ? configure = null )
9799 where TDefaultCommand : class , ICommand
98100 {
99- // Build the DI registrar through the shared bootstrap.
101+ // Build the DI registrar through the shared bootstrap. Awaiting before the using disposes it keeps the
102+ // service provider (and its singletons, e.g. the HttpClient meter factory) alive until the async command
103+ // actually finishes.
100104 using var registrar = BuildRegistrar ( ) ;
101105
102106 // Run a command app whose default command is the supplied type.
103- return CliRunner . RunAsync ( new CommandApp < TDefaultCommand > ( registrar ) , args , configure ) ;
107+ return await CliRunner . RunAsync ( new CommandApp < TDefaultCommand > ( registrar ) , args , configure ) ;
104108 }
105109
106110 /// <summary>
0 commit comments