首页 > 编程语言 >C# 对两个需要顺序执行的函数进行异步交叉,提高执行速度

C# 对两个需要顺序执行的函数进行异步交叉,提高执行速度

时间:2024-01-15 18:33:06浏览次数:26  
标签:异步 getData processData C# num time 执行 data

有的时候我们会有2个函数需要顺序执行,比如将数据库的数据写到硬盘上,

读数据库和写硬盘都是IO比较慢的操作,于是我们很容易就想到让他们异步执行,避免阻塞,提高性能,但是为了保证数据的顺序一致,我们又需要整个队列来存放数据,感觉比较麻烦,今天研究了下,通过异步和信号量控制实现了两个函数异步交叉执行的效果

    internal class Tester {
        int num = 0;
        readonly int time_getData = 2000;
        readonly int time_processData = 1000;
        public async Task Test() {
            await Task.CompletedTask;
            Stopwatch sw = new Stopwatch();
            sw.Start();
            StartCrossLoopTask(GetData, ProcessData);
            sw.Stop();
            var max = (new[] { time_getData, time_processData }).Max();
            var r1 = time_getData + time_processData + max * (num - 1); //除了第一包,后面的都是异步交叉的
            var r2 = (time_getData + time_processData) * num; //同步执行会阻塞
            Console.WriteLine($"实际执行{sw.ElapsedMilliseconds},预估{r1},如果同步执行{r2}");
        }
        string GetData() {
            if (num > 10) return null; //控制退出
            Thread.Sleep(time_getData); //模拟读数据 
            string data = num.ToString();
            Log.Info($"读取数据:{data}");
            num++;
            return data;
        }
        void ProcessData(string data) {
            Thread.Sleep(time_processData); //模拟处理数据
            Log.Info($"                 处理数据:{data}");
        }
        /// <summary>
        /// 开启一个交叉循环任务,这是一个循环任务,先getData获取数据,再processData处理数据,直到getData返回null,
        /// 该函数通过异步和信号量控制,实现了在processData的同时异步getData下一包数据,这样交叉执行,提高了性能
        /// </summary>
        public static void StartCrossLoopTask<T>(Func<T> getData, Action<T> processData) where T : class {
            Semaphore semaphore1 = new Semaphore(1, 1); //获取数据的信号量
            Semaphore semaphore2 = new Semaphore(0, 1); //处理数据的信号量
            T data = null; //接收数据的引用
            Task.Run(() => { //异步执行,实现非阻塞
                while (true) {
                    semaphore1.WaitOne(); //通过信号量控制顺序,保证最多提前获取一包数据,避免不可控的数据堆叠
                    data = getData();
                    semaphore2.Release(); //获取到数据后通知处理函数
                    if (data == null) return; //没有数据时就认为结束了
                }
            });
            T temp = null; //处理数据的引用
            while (true) {
                semaphore2.WaitOne();  //阻塞,等待数据
                if (data == null) return; //这里也得判断退出,否则会卡死
                temp = data;  //将数据指向临时引用,避免引用被覆盖
                semaphore1.Release();  //释放信号量,处理的同时并行获取下一包数据,实现非阻塞
                processData(data); //处理当前包数据
            }
        }
    }

 

标签:异步,getData,processData,C#,num,time,执行,data
From: https://www.cnblogs.com/luludongxu/p/17966015

相关文章

  • C#中var关键字详解:强类型、匿名类型和LINQ查询的妙用!
     在C#中,var关键字是强类型的,因为它在编译时会根据变量的初始化表达式推断出变量的实际类型,并且一旦确定了类型,就不能再更改。这种类型推断是在编译时进行的,因此代码中的变量在运行时是具有明确定义类型的。下面是一个简单的示例,说明var的强类型特性以及使用时的一些注意事项:......
  • 2024-1-15 大数据hive-执行计划
    学习执行计划。简单的解释为:explainquery;一个简单的例子为:explainselectsum(id)fromtest1;该语句的执行计划为:STAGEDEPENDENCIES:Stage-1isarootstageStage-0dependsonstages:Stage-1STAGEPLANS:Stage:Stage-1MapReduceMapO......
  • Porsche Piwis 3 is The Ultimate Porsche Diagnostic Tool
     Piwis3isthethirdgenerationofadiagnostictooldevelopedbyPorscheforuseintheirworkshops.ItisaspecializedpieceofequipmentthatallowsPorschetechniciansandmechanicstodiagnoseandtroubleshootissuesinPorschevehicles.PorscheP......
  • podman和vscode dev container的一些问题
    1.MacArm芯片上podmanmachine启动时卡在CurrentStarting起不来。参考这个链接的回答,更新Qemu的文件https://github.com/containers/podman/issues/21096#issuecomment-1872551224Ihavethesameissue,andalsotriedsomemethodsdiscussedin#21088(comment),none......
  • LSP 网络劫持(Layered Service Provider Hijacking)
    LSP简介:分层服务提供商(LayeredServiceProvider,LSP)是一种可以扩展Winsock作为应用程序的Windows的网络套接字工具的机制。WinsockLSP可用于非常广泛的实用用途,包括Internet家长控制(parentalcontrol)和Web内容筛选。在以前版本的WindowsXP中,删除不正确的(也称......
  • ubuntu18.04+ ROS melodic 安装trac-ik
    IKFast太麻烦了,出现错误太多,安装失败!转而安装Trac-IK,方法很简单,ROS的软件源中已经集成了TRAC-IK的安装包,可以直接使用以下命令安装:sudoapt-getinstallros-melodic-trac-ik然后修改机械臂MoveIt!配置功能包下的kinematics.yaml文件就可以使用啦: arm:kinematics_sol......
  • 前端跨域三种解决方式(CORS、JSONP、代理跨域)
    什么是跨域?跨域是浏览器为了安全而作出的限制策略(所以服务端不涉及到跨域);浏览器请求必须遵循同源策略,即同域名、同端口、同协议;例如:http://www.abc.com到http://www.def.com的请求会出现跨域(域名不同)http://www.abc.com:3000到http://www.abc.com:3001的请求会出现跨域(端口不同......
  • IIC:DDM_SFP光模块参数读取
    光模块数字诊断监控数据读取逻辑报告I2C从设备地址0xA2访问的256字节的数据包括一些常量,也包含一些只读的变量,甚至还有一些可写的变量。数字诊断内存映射专用数据字段描述如下: 图1期间地址分布说明 图2检测信号地址 Finisar公司的DDM数据位于器件地址A2H,具体信号数据......
  • C-strtok-strstr
    strtok字符串分段截取https://www.runoob.com/cprogramming/c-function-strtok.htmlchar*strtok(char*str,constchar*delim)#include<string.h>#include<stdio.h>intmain(){charstr[80]="Thisis-www.runoob.com-website"......
  • 在wpf项目中实现基于Grpc.AspNetCore.Server库的grpc server功能
     前言1.Grpc.Core库的维护到2024.10,之后应该是不再维护了,后续推荐使用Grpc.Net.Client和Grpc.AspNetCore.Server这两个库代替。相关声明信息可以在此处看到,https://grpc.io/blog/grpc-csharp-future/2.当前工作的项目需求是在同一个局域网的多个wpf,通过grpc进行通讯,一个wpf作......