linux 控制台 程序 c 进度条,c# 控制台console进度条

多线程下的输出显示

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

}

}

///

/// 覆写

///

///

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的输出类似。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值