首页 > 编程语言 >C#固定时间间隔触发的计数器

C#固定时间间隔触发的计数器

时间:2023-10-16 09:46:14浏览次数:36  
标签:触发 int string C# long FinishSize 计数器 lastTime public

在运行需要很长时间完成的任务时,一般需要定期展示当前处理进度,比如批量文件复制时,显示复制的文件数和总传输字节数,这时候就需要用计数器对处理任务的完成度进行统计,并以一定时间间隔(如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

相关文章

  • web前端html+css页面内容的六种隐藏方式
    一、使用透明度语法:opacity:0注意:元素消失,但是还会占据空间,只是视觉看不出来<style>.box{width:100px;height:100px;background-color:aquamarine;opacity:0;}</style><divclass="box"></div> 二、使用display语法:display:none注意:元素消失,不会占据空间<style......
  • 题解 AcWing 1272. 与众不同
    题目描述定义完美序列:若一个序列内没有重复的数,称这个数列为完美数列。每次给定一个区间\([l,r]\),求这个区间内最长的完美序列长度。具体思路设\(len_i\)表示从\(i\)出发往右的最长完美序列长度。我们定义一个指针\(st\),表示当前枚举的区间左端点,同时定义多一个指针\(......
  • 【RocketMQ】RocketMQ 5.0新特性(三)- Controller模式
    在RocketMQ5.0以前,有两种集群部署模式,分别为主从模式(Master-Slave模式)和Dledger模式。主从模式主从模式中分为Master和Slave两个角色,集群中可以有多个Master节点,一个Master节点可以有多个Slave节点。Master节点负责接收生产者发送的写入请求,将消息写入CommitLog文件,Slave节点会......
  • PAT_A1070 Mooncake
    MooncakeisaChinesebakeryproducttraditionallyeatenduringtheMid-AutumnFestival.Manytypesoffillingsandcrustscanbefoundintraditionalmooncakesaccordingtotheregion'sculture.Nowgiventheinventoryamountsandthepricesofall......
  • -source 1.5 中不支持方法引用,请使用 -source 8 或更高版本以启用方法引用”的解决方
    https://www.codenong.com/js0e0b40bd9ba3/问题描述:最近在本地打包,时不时遇到如下的报错信息,修改eclipse的Javacompiler和javabuildpath中版本号为1.8,依然未解决  jdk版本过低的报错.png解决方案:1、pom.xml文件增加配置: 12345 <properties>  <pro......
  • 14.6 Socket 应用结构体传输
    当在套接字编程中传输结构体时,可以将结构体序列化为字符串(即把结构体的所有成员打包成一个字符串),然后将字符串通过套接字传输到对端,接收方可以将字符串解析为结构体,然后使用其中的成员数据。这种方法通常被称为序列化(Serialization)和反序列化(Deserialization),本章中我们可以采用将......
  • 部署项目 Failure obtaining db row lock: Table ‘XXX.qrtz_LOCKS‘ doesn‘t exist
    系统环境centos7MySQL5.7原因:mysql对表大小写有要求,但是当时创建表的时候都是小写,所以说就查不到qrtz_LOCKS这张表,所以就报错了解决办法:找到mysql的配置文件my.cnf路径在etc/my.cnfcdetcvimmy.cnf此时点击A键触发编辑命令然后找到位置输入lower_case_table_names......
  • 14.7 Socket 循环结构体传输
    在上述内容中笔者通过一个简单的案例给大家介绍了在套接字编程中如何传递结构体数据,本章将继续延申结构体传输,在某些时候例如我们需要传输一些当前系统的进程列表信息,或者是当前主机中的目录文件,此时就需要使用循环结构体传输功能,循环传输结构体的关键点在于,客户端发送结构体数据......
  • 高效解决方案:Java轻松批量查找与替换Excel文本
    摘要:本文由葡萄城技术团队于博客园原创并首发。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。前言在Excel中,我们经常会使用快捷键Ctrl+F和Ctrl+H对查找的内容进行替换。但是这种情况对于单个的Excel还是很适合的,那如果遇到Excel......
  • TUXEDO宣布Nano Pro Gen12迷你Linux PC搭载AMD Ryzen 7000U处理器
    导读这款迷你PC还配备了AMDMediatekWi-Fi6E三频带芯片,为坚定的AMD粉丝提供了更多选择。TUXEDOComputers今天宣布了NanoPro迷你PC的第12代(Gen12),内部配置升级,连接性改进,计算效率提高。与2021年11月宣布的NanoProGen11相比,NanoProGen12迷你电脑拥有更强大、更高效......