在运行需要很长时间完成的任务时,一般需要定期展示当前处理进度,比如批量文件复制时,显示复制的文件数和总传输字节数,这时候就需要用计数器对处理任务的完成度进行统计,并以一定时间间隔(如500ms)显示当前统计结果。
实现上述功能需要使用一些内部变量来保存当前进度:
long lastSize; long spanSize; long spanTime; long beginTime; long lastTime;
实现add方法,每次内部任务有进度变化时,调用add方法将更新进度保存到内部变量:
public void add(int count, long size) { FinishCount += count; FinishSize += size; long now = DateTime.UtcNow.Ticks; if (now - lastTime > ExpireTime) { spanSize = FinishSize - lastSize; spanTime = now - lastTime; lastTime = now; lastSize = FinishSize; trigger(); } }
一般任务处理线程会非常以非常短的时间间隔(如1ms)更新一次进度,所以add内部不能每次触发外部更新,否则会造成性能问题,所以需要先检查上次外部更新的时间,如果时间间隔超过预先设定的间隔,则触发外部更新,外部更新通知通过TimeIsUp事件实现:
public event Action<Counter> TimeIsUp;
计数器初始化时,可以设定一些初始参数:
public long ExpireTime = 300 * TimeEx.TicksPerMS; public int TotalCount; public int FinishCount; public long TotalSize; public long FinishSize;
如ExpireTime表示外部通知时间间隔,单位为毫秒,TotalCount为子任务数,如果需要统计子任务完成百分比则需要设置此参数,TotalSize为总字节数,如果需要统计任务完成字节数总百分比,则需要设置此参数。
计数器预定了很多统计数据,可以通过公共属性来获取:
public string Speed => $"{SpeedValue.byteSize(2)}/S"; public string AvgSpeed => $"{AvgSpeedValue.byteSize(2)}/S"; public string Duration => (DateTime.UtcNow - new DateTime(beginTime)).ToString(@"hh\:mm\:ss\.ff"); public string SizePair => $"{FinishSize.byteSize(2)}/{TotalSize.byteSize(2)}"; public string CountPair => $"{FinishCount}/{TotalCount}"; public string SizePercent => $"{SizePercentValue}%"; public string CountPercent => $"{CountPercentValue}%"; public string CountInfo => $"{CountPair}, {CountPercent}"; public string FullInfo => $"{SizePercent}, {AvgSpeed}, {CountPair}, {SizePair}, {Duration}"; public string ShortInfo => $"{SizePair}, {CountPair}, {CountPercent}"; public string SpeedInfo => $"{Speed}, {SizePair}, {SizePercent}";
也可以根据需要自定义统计数据。
完整代码:Counter.cs
using System; using util.ext; namespace util { public class Counter { public event Action<Counter> TimeIsUp; public long ExpireTime = 300 * TimeEx.TicksPerMS; public int TotalCount; public int FinishCount; public long TotalSize; public long FinishSize; long lastSize; long spanSize; long spanTime; long beginTime; long lastTime; public Counter() { beginTime = DateTime.UtcNow.Ticks; lastTime = beginTime; } long getSpeed(long size, long time) => (time < ExpireTime) ? 0 : (size * 1000) / (time / TimeEx.TicksPerMS); long SpeedValue => getSpeed(spanSize, spanTime); long AvgSpeedValue => getSpeed(lastSize, lastTime - beginTime); int SizePercentValue => FinishSize.r100(TotalSize); int CountPercentValue => TotalCount <= 0 ? 0 : FinishCount * 100 / TotalCount; public string Speed => $"{SpeedValue.byteSize(2)}/S"; public string AvgSpeed => $"{AvgSpeedValue.byteSize(2)}/S"; public string Duration => (DateTime.UtcNow - new DateTime(beginTime)).ToString(@"hh\:mm\:ss\.ff"); public string SizePair => $"{FinishSize.byteSize(2)}/{TotalSize.byteSize(2)}"; public string CountPair => $"{FinishCount}/{TotalCount}"; public string SizePercent => $"{SizePercentValue}%"; public string CountPercent => $"{CountPercentValue}%"; public string CountInfo => $"{CountPair}, {CountPercent}"; public string FullInfo => $"{SizePercent}, {AvgSpeed}, {CountPair}, {SizePair}, {Duration}"; public string ShortInfo => $"{SizePair}, {CountPair}, {CountPercent}"; public string SpeedInfo => $"{Speed}, {SizePair}, {SizePercent}"; public void update() => add(0, 0); public void addCount(int count = 1) { add(count, 0); } public void addSize(long size) { add(0, size); } public void add(int count, long size) { FinishCount += count; FinishSize += size; long now = DateTime.UtcNow.Ticks; if (now - lastTime > ExpireTime) { spanSize = FinishSize - lastSize; spanTime = now - lastTime; lastTime = now; lastSize = FinishSize; trigger(); } } public void trigger() { TimeIsUp?.Invoke(this); } } }View Code
Github:
https://github.com/bsmith-zhao/vfs/blob/main/util/Counter.cs
参考:
https://github.com/bsmith-zhao/vfs/blob/main/util/Number.cs
https://github.com/bsmith-zhao/vfs/tree/main/util
标签:触发,int,string,C#,long,FinishSize,计数器,lastTime,public From: https://www.cnblogs.com/bsmith/p/17766674.html