间隔10秒处理一次_不想用定时器_我用了异步延时_会降低效率么

张天星 2019-06-30 10:02:04
1、有这么一个需求,我需要每隔10秒钟处理一件事情,比较耗时,可能会处理两三秒。
最开始,我是使用的定时器,定时10秒处理一次。
这就出现了一个问题,定时一次运行,运行两三秒之后结束,然后只过了六七秒,又再次启动了(定时器固定间隔10秒)
这还算简单的,还有一种可能,定时处理的代码,处理不止两三秒,甚至10秒都处理不完,定时器会再次启动,这时候运行了两个一样的逻辑,这个还不能用加锁处理,不然上一次代码运行完,锁一解开马上运行下一次,太坑。。。

后来我换了个想法,用异步:

async void Loop()
{
while(true)
{
执行逻辑();
Task.Delay(10*1000);
}
}

搞了个死循环。
这个倒是可以了,执行一次不管用了十秒还是二十秒,下次启动都是在休息10秒后运行。。。
但是,我想知道,这个思路有没有问题。。。延迟10秒的时候,会不会消耗什么资源,会不会比定时器效率低很多。。
...全文
1510 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
张天星 2020-08-19
  • 打赏
  • 举报
回复
引用 4 楼 wanghui0380 的回复:
另外,从你最近问的问题来说。我觉着你进入了一种误区“总在纠结性能” --------------------------------------- 但是我们不知道你听过另外一句话没有“过早优化是一切问题的根源”------------因为所谓的优化是机巧,机巧其实是违反直觉,违反逻辑的。如果一个写代码的人,天天脑袋写任何一行语句的时候,都在想着“机巧”对不起,你的代码没有任何逻辑,只有各种“回”字的N种写法,任何讨论“回”字用在那里是对的,“茴香豆”就很好这种无聊的搞法 ----------------------------- 请按正常逻辑写,只有他不对的时候再去考虑什么“那种费资源的问题”
去年你的回答其实没看懂,今年再看一次,才算理解。。。
wanghui0380 2019-07-04
  • 打赏
  • 举报
回复
this.btnSwitch.Text == "结束",这类东西少用 task 有CancelToken,有CancelTokenSource控制,不要用那些非线程创建的公共对象 至于定时器和task,得看你是弃还是不弃(排队)。上面有人说单线程的定时器不会并行,但是他是排队。同样ThreadPool.QueueUserWorkItem依旧是排队。 但是如果说你的while呢,那不是排队,而是绝对的前面走了后面补上。 当然异步信号控制也一样,上面有人给你的Monitor也一样,他们也可以查询前面一个走没走,没走?本次弃掉 当然这些都是限流策略,但是你问题不在这里你说cpu问题,你想停100让cpu下来。如果策略成功就好,如果策略不成功,你还是要去找cpu为啥高。 做这种东西,本身不是关心什么Task,定时器问题。首先我们要搞清楚,是并行要求还是并发要求,是IO要求,还是要求。去查是什么引发的问题。然后设计策略“开源”+“节流”,去设计“闸门控制”。 问题不是总和XXX园那样,无端就来个“xxx引发血案”--结论yyy就是xxx好,千万别xxx
wanghui0380 2019-07-04
  • 打赏
  • 举报
回复
无需纠结定时器和Task 当然Task.Delay(1000).Wait(); 这个是同步阻塞,实际效果并不好。我们需要的是异步等待await Task.Delay(1000) 至于定时器和task根本就无需去比较,这不是你项目的核心。也不是引发你卡的原因,别总跟XXX园学什么“一个Task引发的血案”,一个“定时器造成的惨案”-------这些玩意,如果有严谨论证有个印象就好。如果没有严谨论证,看看笑笑就是。
OrdinaryCoder 2019-07-03
  • 打赏
  • 举报
回复
感觉你想要的逻辑是上一次任务执行完10秒之后再启动一个新任务 所以应该有一个标志去判断当前任务的状态 之后有个循环去判断什么时候启动任务
  • 打赏
  • 举报
回复
我觉得你只需要触发定时任务的时候把定时器关掉,处理结束的时候再把定时器开启就好了。
wanghui0380 2019-07-03
  • 打赏
  • 举报
回复
基于上面这样考虑,其实很多问题都可以归一了
引用
这个还不能用加锁处理,不然上一次代码运行完,锁一解开马上运行下一次
为啥不能加锁,当然可以加锁,你只需要让上一次的结尾“冲水10秒”就行
引用
ThreadPool.QueueUserWorkItem
当然可以,还是“上一次的结尾“冲水10秒” 同样的道理 “异步通知”--------一样。冲水10秒后,出门,告诉下一位你可以进来了。 可以看到这么弄都行,无非是“回”字N种用法,所以重要的不是你用什么代码,用什么回字,重要的是你怎么按逻辑写出最符合人类思维的东西,“回”字那是机器思维,“推“还是”敲”得是最后的润色。不是代码的核心
wanghui0380 2019-07-03
  • 打赏
  • 举报
回复
唉,每次都能把问题丢到莫名其妙的地方 假设一群人上厕所,只有一个坑。 那么结果是什么,进去-----脱裤子--xxxx--穿裤子-冲水--出去--下一个人进来 好了,现在穿裤子+冲水要10秒,仅此而已。 所以人家 await Task.Delay(10*1000) //冲水 retrun也好,continue也罢 //都是出去 有问题么,正常操作了。 行了,别扯啥线程,BackgroundWorker,timer,ThreadPool.QueueUserWorkItem 了,一个正常无比的操作,却不知道跑哪里去了
schlafenhamster 2019-07-03
  • 打赏
  • 举报
回复
处理代码 开始 关闭 定时器 , 处理代码 结束 再 设置 定时器
xiaoxiangqing 2019-07-03
  • 打赏
  • 举报
回复
时间太短,不好管制
张天星 2019-07-03
  • 打赏
  • 举报
回复
引用 11 楼 好奇都是要学的 的回复:
[quote=引用 4 楼 wanghui0380 的回复:] 另外,从你最近问的问题来说。我觉着你进入了一种误区“总在纠结性能” --------------------------------------- 但是我们不知道你听过另外一句话没有“过早优化是一切问题的根源”------------因为所谓的优化是机巧,机巧其实是违反直觉,违反逻辑的。如果一个写代码的人,天天脑袋写任何一行语句的时候,都在想着“机巧”对不起,你的代码没有任何逻辑,只有各种“回”字的N种写法,任何讨论“回”字用在那里是对的,“茴香豆”就很好这种无聊的搞法 ----------------------------- 请按正常逻辑写,只有他不对的时候再去考虑什么“那种费资源的问题”
同意,过早的考虑性能是不实在的, 比如你的东西多少人用,在同一时间段内多少人用个,在同一时间内多少人用同一个功能。 就5个人,逻辑没错,优化毫无意义。 但还有一种可能,就是你就是想精进代码,想学习,想换一个思路。想探讨问题。[/quote] 我主要纠结的是定时器和Task.Delay(1000).Wait();这两种延时的机制,有没有差别。想询问哪种比较合适。。。 其他的异步回调之类的操作,需要延时应该也是需要用Task.Delay(1000)的,感觉应该没差别。。。
张天星 2019-07-03
  • 打赏
  • 举报
回复
引用 3 楼 wanghui0380 的回复:
await Task.Delay(10*1000); 不然他只是一个Task
我代码没有抄齐全,完整代码是:Task.Delay(1000).Wait();

Task.Run(() => { LoopRefreshList(); });
private void LoopRefreshList()
        {
            //不想用定时器
            while (this.btnSwitch.Text == "结束")
            {
                _serverInfoRepository.InitData();
                ServerInfoSerivce.RunAllScriptAssist();
                ServerInfoSerivce.RunAllTouchSprite();
                for (int i = 0; i <= 10; i++)
                {
                    this.SetlbDateTime(new TimeSpan(0,0, 10 - i)); //这个是在UI上输出倒计时,下一次刷新处理列表的时间
                    Task.Delay(1000).Wait();
                    if (i == 10) { break; }
                }
            }
        }
引用 20 楼 wanghui0380 的回复:
基于上面这样考虑,其实很多问题都可以归一了
引用
这个还不能用加锁处理,不然上一次代码运行完,锁一解开马上运行下一次
为啥不能加锁,当然可以加锁,你只需要让上一次的结尾“冲水10秒”就行
引用
ThreadPool.QueueUserWorkItem
当然可以,还是“上一次的结尾“冲水10秒” 同样的道理 “异步通知”--------一样。冲水10秒后,出门,告诉下一位你可以进来了。 可以看到这么弄都行,无非是“回”字N种用法,所以重要的不是你用什么代码,用什么回字,重要的是你怎么按逻辑写出最符合人类思维的东西,“回”字那是机器思维,“推“还是”敲”得是最后的润色。不是代码的核心
实现的办法我知道有几种。。。只是不知道哪种比较合适,如果用Task.Delay(1000).Wait();来做延时10秒继续运行,这个本身没问题的话,我就放心了。 主要是这个项目最近很卡。 而整套逻辑中,只有这个循环里面占用的CPU较大,我就在纠结问题出在哪里。
货郎大叔 2019-07-03
  • 打赏
  • 举报
回复
BackgroundWorker组件,不是有一个运行处理完之后的事件么,在这里整个间隔10秒也可以啊
张天星 2019-07-03
  • 打赏
  • 举报
回复
引用 2 楼 秋的红果实 的回复:
更正下:

async void method()
{
    while(条件)
    {
        await Task.Run(处理逻辑);
    }
    
}
那个处理逻辑比较消耗性能,就是从10个安卓模拟器中获取数据,并且监控其中的异常(软件闪退、死机等情况,自动重启设备、自动重启软件等等)。 这个不需要一直运行,我只要求间隔10秒,或者30秒处理一次,所以才做了间隔。 你这个while,应该是会一直循环下去吧,处理完一次又会继续下一次。想知道有没有间隔运行的办法。 我原本是使用定时器,后来就改成了Task.Delay(10*1000),又不知道这么写行不行,最近软件卡的厉害,我又找不到原因,才有点纠结。
足球中国 2019-07-03
  • 打赏
  • 举报
回复
如果timer走的是中断,那么效率是你开线程的N倍。当然没有仔细研究过!!
一个武术猴子 2019-07-02
  • 打赏
  • 举报
回复
用线程 解决呀 Timer 里面有线程的挂起。。。
qq14923349 2019-07-02
  • 打赏
  • 举报
回复
timer里面另起thread
这样timer就不吃时间了,当然有几纳秒差别
网络出错 2019-07-02
  • 打赏
  • 举报
回复
用线程 解决呀 Timer 里面有线程的挂起。。。
baibaipleo 2019-07-01
  • 打赏
  • 举报
回复
这个不可以用Ajax吗 jquery很容易实现吧 但我没接触过winform 如果Ajax返回状态完成 则x=10 计时递归
耗子哭死猫 2019-07-01
  • 打赏
  • 举报
回复
用线程池 ThreadPool.QueueUserWorkItem 上一个执行完再执行下一个
正怒月神 2019-07-01
  • 打赏
  • 举报
回复
你可以根据你的情况,去选择3种不同的timer。 目前根据你说的, 我感觉你适合使用单线程 System.Windows.Forms.Timer 具体你看一下https://blog.csdn.net/hanjun0612/article/details/81357492
加载更多回复(7)

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧