如何使用EventHandler与Parallel.For实现控制台进度条递增
实现控制台进度条结合EventHandler与Parallel.For
1. 给Executer类添加进度更新事件
在Executer类中定义进度更新事件,让外部可以订阅该事件同步更新进度条:
public class Executer { // 定义进度更新事件,传递当前进度百分比 public event EventHandler<int> ProgressUpdated; private int _progress = 0; private readonly int _totalTasks = 99; // 对应Parallel.For(1,100)的99个任务 public void Execute() { Parallel.For(1, 100, i => { DoSomething(); // 原子性递增进度值,避免多线程冲突 int newProgress = Interlocked.Increment(ref _progress); // 触发进度更新事件 OnProgressUpdated(newProgress); }); // 任务全部完成后触发100%进度 OnProgressUpdated(_totalTasks); } private void DoSomething() { // 模拟耗时业务操作 Thread.Sleep(50); } // 线程安全的事件触发方法 protected virtual void OnProgressUpdated(int currentProgress) { int percentage = (int)Math.Round((double)currentProgress / _totalTasks * 100); ProgressUpdated?.Invoke(this, percentage); } }
2. 实现控制台进度条组件
整合控制台进度条的核心逻辑,直接嵌入项目中:
public class ConsoleProgressBar { private const int BarWidth = 50; private readonly char _filledChar = '█'; private readonly char _emptyChar = '░'; public void Update(int percentage) { // 确保百分比在0-100区间内 percentage = Math.Clamp(percentage, 0, 100); // 移动光标到当前行开头,覆盖之前的进度条内容 Console.CursorLeft = 0; // 计算进度条填充长度 int filledLength = (int)Math.Round(BarWidth * percentage / 100.0); string bar = new string(_filledChar, filledLength) + new string(_emptyChar, BarWidth - filledLength); // 输出进度条与百分比 Console.Write($"[{bar}] {percentage,3}%"); // 进度完成后换行,避免后续输出覆盖进度条 if (percentage == 100) { Console.WriteLine(); } } }
3. 在主程序中绑定事件并启动任务
在Main方法里订阅进度更新事件,同步更新控制台进度条:
class Program { static void Main(string[] args) { var progressBar = new ConsoleProgressBar(); var executer = new Executer(); // 订阅进度更新事件,线程安全地更新进度条 executer.ProgressUpdated += (sender, percentage) => { lock (progressBar) { progressBar.Update(percentage); } }; Console.WriteLine("任务启动..."); executer.Execute(); Console.WriteLine("任务完成!"); } }
关键注意事项
- 线程安全:用
Interlocked.Increment保证进度值的原子性;控制台输出加lock,避免多线程同时写入导致的界面混乱。 - 事件触发:通过
OnProgressUpdated方法触发事件,用?.Invoke避免空引用异常。 - 进度准确性:根据总任务数计算百分比,确保进度条最终能显示100%完成状态。
内容的提问来源于stack exchange,提问作者Yogi_Bear
相关产品推荐
相关产品推荐

