What is the best way to use Progress? #162
-
Hey guys, i'm writing a downloader and i want to show the download progress of the files. I have a list of "DownloadItem", after collecting this items, a method creates tasks. store the tasks in a list and after that, i wait of all tasks with In the task, i download the file with a HttpClient and use the Progress class, to notify a method of the current status of the download. But i dont know, how i should use the |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 3 replies
-
@reneduesmann Below is some code that will download some files using Hope it helps! using Spectre.Console;
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
var client = new HttpClient();
var items = new (string name, string url)[]
{
("Ubuntu 20.04", "https://releases.ubuntu.com/20.04.1/ubuntu-20.04.1-desktop-amd64.iso"),
("Spotify", "https://download.scdn.co/SpotifySetup.exe"),
("Windows Terminal", "https://github.com/microsoft/terminal/releases/download/v1.5.3242.0/Microsoft.WindowsTerminalPreview_1.5.3242.0_8wekyb3d8bbwe.msixbundle"),
};
// Progress
await AnsiConsole.Progress()
.Columns(new ProgressColumn[]
{
new TaskDescriptionColumn(),
new ProgressBarColumn(),
new PercentageColumn(),
new RemainingTimeColumn(),
new SpinnerColumn(),
})
.StartAsync(async ctx =>
{
await Task.WhenAll(items.Select(async item =>
{
var task = ctx.AddTask(item.name, new ProgressTaskSettings
{
AutoStart = false
});
await Download(client, task, item.url);
}));
});
// This methods downloads a file and updates progress
async Task Download(HttpClient client, ProgressTask task, string url)
{
try
{
using (HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
{
response.EnsureSuccessStatusCode();
// Set the max value of the progress task to the number of bytes
task.MaxValue(response.Content.Headers.ContentLength ?? 0);
// Start the progress task
task.StartTask();
var filename = url.Substring(url.LastIndexOf('/') + 1);
AnsiConsole.MarkupLine($"Starting download of [u]{filename}[/] ({task.MaxValue} bytes)");
using (var contentStream = await response.Content.ReadAsStreamAsync())
using (var fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None, 8192, true))
{
var buffer = new byte[8192];
while (true)
{
var read = await contentStream.ReadAsync(buffer, 0, buffer.Length);
if (read == 0)
{
AnsiConsole.MarkupLine($"Download of [u]{filename}[/] [green]completed![/]");
break;
}
// Increment the number of read bytes for the progress task
task.Increment(read);
// Write the read bytes to the output stream
await fileStream.WriteAsync(buffer, 0, read);
}
}
}
}
catch (Exception ex)
{
// An error occured
AnsiConsole.MarkupLine($"[red]Error:[/] {ex}");
}
} |
Beta Was this translation helpful? Give feedback.
-
Hey @patriksvensson, But do you have a idea, how to use it with Progress? |
Beta Was this translation helpful? Give feedback.
-
Here is my code with System.Progress @patriksvensson
I create a new instace of the Progress like
And give it the above code. The workflow is, i collect all items, that will be downloaded and call a method that have this code
But i dont know, how to implement the Spectre Progress to that. |
Beta Was this translation helpful? Give feedback.
-
I've made example of console app using // See https://aka.ms/new-console-template for more information
using Spectre.Console;
class Program
{
class ProgressInfo
{
public double Task1Increase { get; set; }
public double Task2Increase { get; set; }
}
class AnsiConsoleProgress
{
private readonly ProgressTask _task1;
private readonly ProgressTask _task2;
private readonly object _consoleLock = new object();
public AnsiConsoleProgress(ProgressTask task1, ProgressTask task2)
{
_task1 = task1;
_task2 = task2;
}
public void ReportProgress(ProgressInfo info)
{
lock (_consoleLock)
{
_task1.Increment(info.Task1Increase);
_task2.Increment(info.Task2Increase);
}
}
}
public static async Task Main(string[] args)
{
AnsiConsole.WriteLine("Start");
await AnsiConsole.Progress()
.StartAsync(async ctx =>
{
// Define tasks
var task1 = ctx.AddTask("[green]Reticulating splines[/]");
var task2 = ctx.AddTask("[green]Folding space[/]");
var ansiProgress = new AnsiConsoleProgress(task1, task2);
var progress = new Progress<ProgressInfo>(ansiProgress.ReportProgress);
await DoAsync(progress);
});
AnsiConsole.WriteLine("Finish");
}
private static async Task DoAsync(IProgress<ProgressInfo> progress)
{
int counter = 0;
while(counter < 200)
{
await Task.Delay(100);
counter++;
progress.Report(new ProgressInfo { Task1Increase = 1.5, Task2Increase = 0.5 });
}
}
} |
Beta Was this translation helpful? Give feedback.
@reneduesmann Below is some code that will download some files using
HttpClient
andawait Task.WhenAll
and shows progress.The example uses C# 9, top-level programs, and Spectre.Console version
0.33.1-preview.0.1
.Hope it helps!