diff --git a/src/EasilyNET.Core/Misc/TextWriterExtensions.cs b/src/EasilyNET.Core/Misc/TextWriterExtensions.cs
new file mode 100644
index 00000000..31880a12
--- /dev/null
+++ b/src/EasilyNET.Core/Misc/TextWriterExtensions.cs
@@ -0,0 +1,117 @@
+using EasilyNET.Core.Threading;
+
+// ReSharper disable UnusedMember.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+
+namespace EasilyNET.Core.Misc;
+
+///
+/// 扩展方法
+///
+public static class TextWriterExtensions
+{
+ private static readonly AsyncLock _lock = new();
+
+ ///
+ /// 线程安全的控制台在同一行输出消息
+ ///
+ ///
+ /// 使用方式:
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task SafeWriteOutput(this TextWriter writer, string msg)
+ {
+ using (await _lock.LockAsync())
+ {
+ ClearCurrentLine();
+ await writer.WriteAsync(msg);
+ }
+ }
+
+ ///
+ /// 线程安全的清除当前行
+ ///
+ ///
+ /// 使用方式:
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task SafeClearCurrentLine(this TextWriter _)
+ {
+ using (await _lock.LockAsync())
+ {
+ ClearCurrentLine();
+ }
+ }
+
+ private static void ClearCurrentLine()
+ {
+ Console.SetCursorPosition(0, Console.CursorTop);
+ Console.Write(new string(' ', Console.WindowWidth));
+ Console.SetCursorPosition(0, Console.CursorTop);
+ }
+
+ ///
+ /// 在控制台输出进度条,用于某些时候需要显示进度的场景
+ ///
+ /// Writer
+ /// 进度
+ /// 消息
+ /// 进度条整体宽度,包含消息部分
+ /// 完成部分填充字符
+ /// 未完成部分填充字符
+ ///
+ ///
+ /// 使用方式:
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task ShowProgressBar(this TextWriter writer, double progressPercentage, string message = "", int totalWidth = -1, char completedChar = '=', char incompleteChar = '-')
+ {
+ if (progressPercentage < 0) progressPercentage = 0;
+ if (progressPercentage > 100) progressPercentage = 100;
+ var progressText = $"{progressPercentage / 100.0:P1}";
+ var extraWidth = progressText.Length + message.Length + 5; // 计算额外字符的宽度,包括边界和百分比信息
+ try
+ {
+ // 确保 totalWidth 不为负数
+ totalWidth = totalWidth == -1 ? Math.Max(0, Console.WindowWidth - extraWidth) : Math.Max(0, totalWidth - extraWidth);
+ }
+ catch (Exception)
+ {
+ // 如果 Console.WindowWidth 抛出异常说明当前环境不支持,则将 totalWidth 设置为 80
+ totalWidth = Math.Max(0, 80 - extraWidth);
+ }
+ var progressBarWidth = (int)progressPercentage * totalWidth / 100;
+ if (Math.Abs(progressPercentage - 100) < 0.000001) progressBarWidth = totalWidth; // 确保在100%时填满进度条
+ var progressBar = new string(completedChar, progressBarWidth).PadRight(totalWidth, incompleteChar);
+ var output = $"[{progressBar}] {progressText} {message}";
+ await writer.SafeWriteOutput(output);
+ }
+}
\ No newline at end of file