ライブプログレスバー - Spectre Console シリーズ
Spectre.Consoleライブラリは、普通のC#コンソールアプリケーションを視覚的に魅力的で有益なツールに変えることを目的としています。 最も印象的な機能の1つは、アプリケーションの動作に合わせて更新されるプログレスバーを表示する機能です。 これは、ユーザーに情報を提供し続けたい長期的なタスクに非常に役立ちます。
Live Progress Bars - Spectre Console Series"ビデオでは、Tim Corey 氏が C# Spectre Console プログレスバーの作成方法をステップごとに紹介しています。
コンソール アプリケーションのセットアップ
ビデオの冒頭(0:00)でティムはSpectre.Consoleコンソール・ライブラリを紹介し、ソースコードのリンクがビデオの下にあることを示します。 彼は視聴者に、これらはあなたの一日に合わせることができる10分のチャンクであることを思い出させる。
Timは、通常のC#コンソールアプリで作業しています。クラスProgramとstatic void Main(string[雛形] args)を持つ単純な定型ファイルを考えてください。 特別なUIフレームワークを使っているわけではなく、Spectre.ConsoleへのNuGetパッケージの参照だけです。 これは、Windowsターミナルやコンソールホストにこれらの機能を持ち込むことができることを思い出させる良いものです。
進行状況の作成
0:34から、Timがコーディングを始めます。 Main メソッドでは、AnsiConsole.Progress() を呼び出し、.Start() を実行しています。 これは、Spectre.Console のプログレスバーの標準的なエントリポイントです。
彼は、ラムダにコンテキスト・パラメータを渡すことを示しています。これは、後で非同期にするときにasync ctxとして考えることができます。 このような状況の中で、あなたのタスクを定義します。 これは、Spectre.Console の更新を開始する前に進行中のタスクを設定することに相当します。
進捗タスクを追加する
ティムは3つの進捗タスクを作成します:
"データのダウンロード"
"アプリケーションのインストール"
- "データクリーンアップ"
各タスクは、var task = context.AddTask("...")で追加されます。 これらは、後でインクリメントできるタスクハンドルを返します。 Timは(1:22)、Spectre.Consoleは新しいProgressBarColumn、新しいPercentageColumn、新しいSpinnerColumn、新しいTaskDescriptionColumnを追加して、バーの外観をカスタマイズするなど、さまざまなスタイル、カラム、レイアウトをサポートしています。
彼はこの作業をVisual Studioのインストーラーに例えている。ダウンロード、インストール、そしてクリーンアップだ(1:42)。 各タスクがintパーセントまたはint値を内部的に保持しながら更新している様子を想像してください。
プログレス バーの更新
1:50で、Timはコンテキストが終わるまで実行されるwhileループをセットアップする。 実際のC#コンソールプログラムでは、Mainメソッドの中にwhile (!context.IsFinished)またはwhile (context.IsFinished == false)と書くことがあります。
ループの内部で、彼はThread.Sleep(500)を呼び出してスローダウンさせている(2:15)。 彼は次に、ランダムなダブルに最大値を掛けたtask.Increment()を呼び出す(2:29, 2:47)。 これは、行われている作業をシミュレートします。
彼は、タスク1とタスク2を異なるスピードで更新し、タスク3については、タスク2のパーセンテージが80より大きくなってから開始するように、ifチェック(3:05)を追加している。これは基本的に、進行中のタスク間の依存関係をコントロールするものである。
Timはforeachループの中で文字通りint iをタイプしませんが、タスクを繰り返し処理し、それぞれに対して.Increment(int)を呼び出すためにforeachループを使用することは想像できます。 本番環境では、varクライアントがファイルをダウンロードしたり、文字列のファイル名が処理されるなど、実際のデータが使用される可能性があります。 ティムは、表示を示すために乱数を用いてシンプルにしています。
プログレス バーの表示と観察
3:47にTimがコンソールアプリケーションを実行します。 プログレスバーが積み重なって表示されます。 各バーは最後にパーセンテージを示し、完了すると緑色に変わります(4:01)。 最初の作業が終わると、"データのクリーンアップ"が始まります。
4:14でTimはカーソルがコンソールの一番下に戻ることを指摘していますが、これは些細なことですが重要なユーザビリティのディテールです。 Spectre.Consoleのプログレスバーは、ステータスを自動的にフォーマットし、ちらつきなくすべてを維持します。
待ちタスクで非同期を実現する
4:36でTimはギアを切り替え、非同期バージョンを見せる。 彼は.Start()を.StartAsync()に変更し、ラムダをasyncとマークしています。 現在、context パラメータは async ctx のように動作します。
内部ではThread.Sleepの代わりにawait Task.Delay(500)を使っている(4:58)。 これにより、待ち時間の間、システムにコントロールが戻ります。 実際のプログラムでは、await client.DownloadAsync()やawait AnsiConsole.MarkupAsync()のように、バーと一緒にステータステキストを表示するような実際の操作を待っているかもしれません。
非同期バージョンは、視覚的にはまったく同じように機能しますが(5:16-5:23)、最新の非同期ワークフローにより適しています。 Timは表示していませんが、待ち受けるタスクの周りでtry/catch(Exception ex)を使って例外を捕捉することもできます。

オートクリアと仕上げ
Timは、Spectre.Consoleがデフォルトで画面上の完了タスクを100%のままにしていることに気づきました。 自動的に消えてほしい場合は、進捗を設定した後に .AutoClear(true) を呼び出してください(5:42)。 作業が終わると、バーは瞬時に消える(6:02)。

これは、一時的に進捗レポートを表示するだけでよく、コンソール出力を乱雑にしたくない場合に便利です。 インタラクティブなプロンプト、新しいパネル表示、あるいは Spectre.Console の var テーブルと組み合わせることで、ダイナミックなダッシュボードスタイルのコンソール UI を作成できます。
基本を超えて - さまざまなスタイルとカラム
最後の数分で、Timはまだまだ探求すべきことがたくさんあると述べている(6:11)。 フォーマット、色、レイアウトを変更したり、異なるカラムタイプを使用したりすることができます。たとえば、新しい棒グラフ、新しいテーブルを追加したり、新しいパネルとプログレスバーを組み合わせて、グループ化された結果を表示したりできます。
Spectre.Consoleのドキュメントでは、新しいProgressColumnの実装を混ぜる方法や、各タスクの最大値を調整する方法、さらにはスペースを節約するために複数のタスクを1つのバーに折りたたむ方法("折りたたみスペース")を紹介しています。 コンソールアプリケーション内で、カウント数、合計数、ファイル名、ユーザー名、または処理中のパスワードを表示するために使用できます。
結論
ティムは、ビデオの最後で、次のことを説明しました:
ゼロから作られた Spectre Console プログレスバー
複数の進捗タスクを定義して更新する方法
Thread.Sleepで同期的に、またはawait Task.Delayで非同期的に実行する方法
.AutoClear(true)を使用して終了したバーをクリアする方法
- より高度なスタイリングとドキュメンテーションのための場所
この小さなデモでは、C#コンソールプログラムにプロフェッショナルなプログレスバーを簡単に導入できることを紹介しています。 Spectre.ConsoleのNuGetパッケージと数行のコードを使用するだけで、ステータスを表示したり、パーセンテージを表示したり、アプリが何をしているのかをより明確にユーザーに伝えることができます。

