c#控制台console进度条(代码片段)

hsxian hsxian     2022-12-16     774

关键词:

1 说明

笔者大多数的开发在 Linux 下,多处用到进度条的场景,但又无需用到图形化界面,所以就想着弄个 console 下的进度条显示。

2 步骤

  1. 清行显示

    //清行处理操作
    int currentLineCursor = Console.CursorTop;//记录当前光标位置
    Console.SetCursorPosition(0, Console.CursorTop);//将光标至于当前行的开始位置
    Console.Write(new string(' ', Console.WindowWidth));//用空格将当前行填满,相当于清除当前行
    Console.SetCursorPosition(0, currentLineCursor);//将光标恢复至开始时的位置

    如果要清除上一行,只需在清行处理操作前将调整光标位置提前一行,即:Console.SetCursorPosition(0, Console.CursorTop - 1);。紧接着Console.WriteLine(/*something*/);,即可实现在控制台末尾行重复输出。

  2. 多线程下的输出显示

    多线程下最容易出现的问题就是一个线程的输出覆盖其他线程的输出,或者是一个线程紧跟着上一个线程输出而没有换行,这些情况多会导致输出的混乱。为了,解决这样的问题,特意实现一个专门的输出类来进行输出显示:

     public class Consoler
     
         private static string lastContext = "";//用于记录上次写的内容
         private static readonly object _lock = new object();//加锁保证只有一个输出
         public static void Write(string context)
         
             lastContext = context;//记录上次写的内容
             lock (_lock)
             
                 Console.Write(context);
             
    
         
         /// <summary>
         /// 覆写
         /// </summary>
         /// <param name="context"></param>
         public static void OverWrite(string context = null)
         
             lastContext = context;//记录上次写的内容
             var strLen = context?.Length ?? 0;
             //空白格的长度,考虑到内容可能超出一行的宽度,所以求余。
             var blankLen = strLen % Console.WindowWidth;
             Console.SetCursorPosition(0, Console.CursorTop);
             //空白只需填充最后一行的剩余位置即可。
             lock (_lock)
             
                 Console.Write(context + new string(' ', Console.WindowWidth - blankLen));
             
         
    
         public static void WriteLine(string context = null)
         
             ClearConsoleLine();//清除最后一行
             lock (_lock)
             
                 Console.WriteLine(context);
                 if (!string.IsNullOrWhiteSpace(lastContext))
                     Console.Write(lastContext);//重新输出最后一次的内容,否则有较明显的闪烁
                 lastContext = null;
             
         
    
         public static void ClearConsoleLine(int invertedIndex = 0)
         
             int currentLineCursor = Console.CursorTop;
             int top = Console.CursorTop - invertedIndex;
             top = top < 0 ? 0 : top;
             Console.SetCursorPosition(0, top);
             Console.Write(new string(' ', Console.WindowWidth));
             Console.SetCursorPosition(0, currentLineCursor);
         
     

    实际测试时,使用多 Task (模拟多线程)去进行输出实验:

    static void Main(string[] args)
     
         Console.WriteLine("Hello World!");
    
         var task1 = Task.Run(() =>
         
             int count = 0, w = (int)(Console.WindowWidth * 0.6), lw = 0, rw = 0;
             float p = 0;
             while (true)
             
                 count %= 75;
                 p = count++ / 74f;
                 lw = (int)(p * w);
                 rw = w - lw;
                 Consoler.OverWrite($"from task1, [new string('#', lw) + new string(' ', rw)]:p:#.00%");
                 Thread.Sleep(100);
             
         );
         var task2 = Task.Run(() =>
         
             while (true)
             
                 Consoler.WriteLine($"from task2, now:DateTime.Now");
                 Thread.Sleep(5000);
             
         );
    
         var task3 = Task.Run(() =>
         
             var rd = new Random();
             while (true)
             
                 Consoler.WriteLine($"from task3, new string('+', (int)(rd.NextDouble() * Console.WindowWidth))");
                 Thread.Sleep(rd.Next(5000));
             
         );
         Task.WaitAll(task1);
     

    最终输出结果:

     from task2, now:6/5/19 8:10:24 PM
     from task3, +++++++++++++++++++++++++++++++++
     from task2, now:6/5/19 8:10:29 PM
     from task3, +++++++++++++++++++++++++
     from task3, ++++
     from task2, now:6/5/19 8:10:34 PM
     from task3, +++++++++++++++++++++++
     from task3, ++++++++++++
     from task3, ++++++
     from task2, now:6/5/19 8:10:44 PM
     from task1, [###########################                     ]:58.11%

    task1 用来进行进度条的输出,task2 和 task3 进行随机输出。可以看出,task1 永远在最后一行进行进度更新,其他输出任然可以正常进行。实现的效果和 ubuntu 下执行更新命令sudo apt-get update的输出类似。

  3. 总结

    虽然该例子是在 c#下完成的,但在 python,c,java 中通用。为了保证输出的有序性,程序中加了锁,影像了多线程的效率,但是对于界面显示是足够的。如果需要高性能,那么考虑使用类似于队列式的异步更新输出显示的方法。

java控制台示例中的java进度条(代码片段)

查看详情

python实用工具用python在控制台输出进度条(代码片段)

 进度条在一些计时任务中会经常使用,这里提供两种在控制台输出进度条显示的简单源代码:#进度条1importtimeforiinrange(1,101):print('\\r'+'▋'*i+'当前进度:%'.format(i),end='')time.sleep(0. 查看详情

实现winfrom进度条及进度信息提示,winfrom程序假死处理(代码片段)

...能描述:在用c#做WinFrom开发的过程中。我们经常需要用到进度条(ProgressBar)用于显示进度信息。这时候我们可能就需要用到多线程,如果不采用多线程控制进度条,窗口很容易假死(无法适时看到进度信息)。下面我就简单结... 查看详情

python文本进度条(代码片段)

文本进度条:编程通过格式化字符串输出和时间延迟实现控制台风格文本进度条绘制效果如上图importtimescale=10print("执行开始".center(scale,'-'))foriinrange(scale+1):a='*'*ib="."*(scale-i)c=(i/sc 查看详情

(68)c#里怎么样提供一个有窗口显示进度条的拷贝目录的功能(代码片段)

(68)C#里怎么样提供一个有窗口显示进度条的拷贝目录的功能在C#里开发,常常会遇到拷贝大目录的文件,比如很多LOG日志,运行时间久了,需要把它们备份起来,那么就需要拷贝这些文件,这时候就会比较久,如果不显示一个... 查看详情

学习进度条

 第四周所花时间(小时)8代码量(行)400博客量(篇)2所学到的知识学习《软件需求模式》的第五、六章,学习编写C#控制台程序,对基本的输入输出还有变量、数组的定义有了一定的了解,学习安装Oracle数据库。  查看详情

c#进度条怎么用/c#progressbar的用法

1.打开MicrosoftVisualStudio2010,新建名字为【进度条】的程序。2.在新程序界面上放置合适的控件:包括,日志输出文本框控件;用于输入进度条长度的输入框;3个进度条的控制按钮,可以分别开始、暂停或者停止进度条的进度;添... 查看详情

c#如何根据文件数量控制进度条

c#根据文件的数量来控制进度条,也就是说,复制完一个文件,进度条前进一点,进度条的最大值是文件的数量说实话,关于进度条的解决方案很多,我暂且假定你在做Winform程序开发。如果你使用的StatusBar中的进度条的话,你可... 查看详情

c#控制台设置(代码片段)

我们经常使用控制台做一些代码的测试、调试,这样方便又快捷,但是控制台的相关用法我们日常可能使用到的很少,这节就展示一些你可以很少用到但是有很使用的控制台设置方法.字体颜色设置: Console.Foregrou... 查看详情

c#通过线程来控制进度条(转)--讲解多线程对界面的操作

//通过创建委托解决传递参数问题privatevoid_btnRun_Click(objectsender,System.EventArgse){RunTaskDelegaterunTask=newRunTaskDelegate(RunTask);//委托同步调用方式runTask(Convert.ToInt16(_txtSecond.Value));}//通过创建委托解决传递参数问题,通过委托的 查看详情

csharp控制台进度条。代码属于麻省理工学院许可证:http://opensource.org/licenses/mit(代码片段)

查看详情

csharp控制台进度条。代码属于麻省理工学院许可证:http://opensource.org/licenses/mit(代码片段)

查看详情

c#上位机开发——多线程+进度条的使用(代码片段)

1.界面设计2.使用多线程修改进度条引入多线程类库命名空间:usingSystem.Threading;将变量添加到Form1类:privateThreadth;将方法添加到Form1类:privatevoidThreadTask()intstp;intnewval;Randomrnd=newRandom();while(true)stp=this.progressBar1.Step... 查看详情

c#上位机开发——多线程+进度条的使用(代码片段)

1.界面设计2.使用多线程修改进度条引入多线程类库命名空间:usingSystem.Threading;将变量添加到Form1类:privateThreadth;将方法添加到Form1类:privatevoidThreadTask()intstp;intnewval;Randomrnd=newRandom();while(true)stp=this.progressBar1.Step... 查看详情

进度条的美化(代码片段)

这里记录一种用css控制进度条美化的效果css代码:@-webkit-keyframesprogress-bar-stripesfrombackground-position:40px0tobackground-position:00@-moz-keyframesprogress-bar-stripesfrombackground-position:40px0tobackgro 查看详情

使用jquery给网站添加下载进度显示(代码片段)

...给页面。下面的代码显示了通过jquery发送ajax请求,并在控制台显示进度信息1$.ajax(2url:‘/api/version‘,3type:‘post‘,4dataType:‘json‘,5data:paperid:paperid,version:filename,6statusCode:7200:function(json),8,9xhr:function()10varxhr=newwindow.XMLHttpRequest();11//do... 查看详情

c#欢迎画面显示程序启动进度条,并自动打开主界面(代码片段)

...加载时先启动后台线程进行延时操作,并实时显示到进度条上,待进度条完成后(也就是线程结束)程序会自动响应线程结束事件(注意这个响应事件是主线程上的,所以操作控件界面等等都不影响)&... 查看详情

c#利用for循环打印图形练习题(代码片段)

(1)namespaceConsoleApp2classProgramstaticvoidMain(string[]args)for(inti=0;i<5;i++)//外层循环控制的是行数for(intj=0;j<=i;j++)//内层循环控制的是列数,控制是每行打印的内容及个数Console.Write("*");Console.WriteLine();Console. 查看详情