spectre.console
spectre.console copied to clipboard
StartAsync can block
Information
- OS: Windows
- Version: 0.43.0
- Terminal: Windows Terminal
Describe the bug
When starting a progress task with StartAsync, I would expect a new task to be created inside of StartAsync via TaskFactory.StartNew in order for it to be non-blocking when synchronous code is inside of the StartAsync action. Currently in the example, the 'otherTask' line is not hit until the progress is completed.
var progressTask = AnsiConsole.Progress()
.StartAsync(async ctx =>
{
// Define tasks
var task1 = ctx.AddTask("[green]Reticulating splines[/]");
var task2 = ctx.AddTask("[green]Folding space[/]");
while (!ctx.IsFinished)
{
// Simulate a synchronous operation like a database driver that may not have asynchronous I/O.
Thread.Sleep(5000);
// Increment
task1.Increment(1.5);
task2.Increment(0.5);
}
});
var otherTask = Task.StartNew(() => doStuff());
Task.WaitAll(progressTask, otherTask).
To Reproduce
Shown Above. Workarounds are wraping AnsiConsole.Progress in a TaskFactory.StartNew or have await Task.Yield() inside of the action of StartAsync.
Expected behavior
StartAsync would be non-blocking even if there are blocking things inside of StartAsync's action.
If you run AnsiConsole.Progress().StartAsync() then action parameter should contain await operations to use async feature. I think that using only sunchronous operations inside StartAsync require to use Task.Run and it's correct solution. Your sample should look more like this:
var progressTask = AnsiConsole.Progress()
.StartAsync( async ctx =>
{
var task1 = ctx.AddTask( "[green]Reticulating splines[/]" );
while ( !ctx.IsFinished )
{
await Task.Delay( 1000 );
task1.Increment( 50 );
AnsiConsole.WriteLine( task1.Value );
}
} );
var otherTask = Task.Run( () => AnsiConsole.WriteLine( "Other stuff" ) );
await Task.WhenAll( progressTask, otherTask );
AnsiConsole.WriteLine( "Done" );
Then you will see in the output
Other stuff
50
100
Has @danielklecha's comment above fixed this issue for you @kuhnboy?