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 = Console.WindowWidth - strLen % Console.WindowWidth - 1;
    var rowCount = strLen / Console.WindowWidth;
    Console.SetCursorPosition(0, Console.CursorTop - rowCount);
    //空白只需填充最后一行的剩余位置即可。
    lock (_lock)
    {
    Console.Write(context + new string(' ', 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 - 1));
    Console.SetCursorPosition(0, currentLineCursor);
    }
    }

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

    static void Main(string[] args)
    {
    Console.WriteLine("Hello World!"); var task1 = Task.Run(() =>
    {
    int count = 0, w, lw, rw;
    float p = 0;
    while (true)
    {
    w = (int)(Console.WindowWidth * 0.6);
    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 中通用。为了保证输出的有序性,程序中加了锁,影像了多线程的效率,但是对于界面显示是足够的。如果需要高性能,那么考虑使用类似于队列式的异步更新输出显示的方法。

c# 控制台console进度条的更多相关文章

  1. Python 控制台进度条的实现

    进行爬虫等耗时的任务时,有时会想在控制台输出进度条,以显示当前任务进度.这里总结了两种方法. 方法1:使用tqdm模块 示例代码: from time import sleep from tqdm i ...

  2. 用C#实现控制台进度条

    在写一些简单的控制台测试程序时,经常希望能够在程序运行的过程中实现进度条的功能以便查看程序运行的速度或者进度.本文以C#为例,实现简单的控制台进度条,以供大家参考(本文底部附下载地址). 1.实现效果 ...

  3. [c#]控制台进度条的示例

    看到[vb.net]控制台进度条的示例 感觉很好玩,翻译成C#版. using System; using System.Collections.Generic; using System.Linq; ...

  4. [golang]golang如何覆盖输出console,实现进度条;golang一个骚气的进度提示库

    [golang]golang如何覆盖输出console,实现进度条 package main import( "fmt" "os" "time&quo ...

  5. 小技巧:with用法 pycharm控制台输出带颜色的文字 打印进度条的

    with用法 with用法在python中是一个很独特的用法,因为别的语言的中没有这个用法.所以针对这个特点我们来做一次总结,什么样的情况下可以同with  我们学到的有文件的操作,和acquire  ...

  6. ruby 编写控制台进度条

    ruby 中,$stdout.flush 让控制台当前行内容可以重写,以此我们可以做出进度条的效果. def set_progress(index, char = '*') print (char * ...

  7. 《C/C++实现Console下的加载进度条模拟[美观版]》

    前言   有时候我们会遇到在CMD或DOS控制台上出现的加载进度条,虽然不是如网页和软件写的美观.但确确实实也有着自己的特色.而且,一个好看的加载进度条也能增加用户使用控制台程序的体验!所以,拿来研究 ...

  8. Python中如何写控制台进度条的整理

    本文实例讲述了Python显示进度条的方法,是Python程序设计中非常实用的技巧.分享给大家供大家参考.具体方法如下: 首先,进度条和一般的print区别在哪里呢? 答案就是print会输出一个\n ...

  9. Ajax上传文件进度条显示

    要实现进度条的显示,就要知道两个参数,上传的大小和总文件的大小 html5提供了一个上传过程事件,在上传过程中不断触发,然后用已上传的大 小/总大小,计算上传的百分比,然后用这个百分比控制div框的显 ...

随机推荐

  1. Codeforces Round #563 (Div. 2)B

    B.Ehab Is an Odd Person 题目链接:http://codeforces.com/contest/1174/problem/B 题目 You’re given an array a ...

  2. Java字符串String类操作方法详细整理

    关于String类的基本操作,可分为以下几类: 1.基本操作方法 2.字符串比较 3.字符串与其他数据类型之间的转换 4.字符与字符串的查找 5.字符串的截取与拆分 6.字符串的替换与修改 我觉得在整 ...

  3. IAR for STM8的简介、下载、安装及注册教程

    一.简介 1.关于IAR for STM8 IAR for STM8 是一个嵌入式工作平台,主要应用于STM8 系列芯片的开发,现在(2018年3.10版本)能够支持市面上所有的STM8芯片. 个人认 ...

  4. python初识(3)

    bool 字符串 for循环 bool 数字非零全都是True 字符串非空全都是True 字符串 索引 从0开始 0 切片选取 [x:y] 左闭右开区间 [x:y:z] 选取x到y之间 每隔z选取一次 ...

  5. 使用开源框架Sqlsugar结合mysql开发一个小demo

    一.Sqlsugar简介 1.性能上有很大优势 sqlsugar是性能最好的ORM之一,具有超越Dapper的性能 ,走的是EMIT够构中间语言动态编译到程序集,完成高性能的实体绑定,达到原生水平. ...

  6. C语言学习书籍推荐《Practical C++ Programming》下载

    下载链接 :点我 C++ is a powerful, highly flexible, and adaptable programming language that allows software ...

  7. Elasticsearch(二)集群设置

    Elasticsearch支持多播和单播自动发现节点,但多播已经不被大多数操作系统支持,并且安全性不高,这里主要用单播发现节点,配置如下 discovery.zen.ping.multicast.en ...

  8. 基于SpringCloud的Microservices架构实战案例-在线API管理

    simplemall项目前几篇回顾: 1基于SpringCloud的Microservices架构实战案例-序篇 2基于SpringCloud的Microservices架构实战案例-架构拆解 3基于 ...

  9. 剑指offer第二版-8.二叉树的下一个节点

    描述:给定一棵二叉树和其中的一个节点,找出中序遍历序列的下一个节点.树中应定义指向左节点.右节点.父节点的三个变量. 思路: 1.如果输入的当前节点有右孩子,则它的下一个节点即为该右孩子为根节点的子树 ...

  10. C# .net Ueditor实现图片上传到阿里云OSS 对象存储

    在学习的时候,项目中需要实现在Ueditor编辑器中将图片上传到云储存中,老师演示的是上传到又拍云存储,既然看了一遍,直接照搬不算本事,咱们可以依葫芦画瓢自己来动手玩玩其它的云存储服务. 现在云计算产 ...