WPF-23 基于Timer任务调度

.NET的FCL中提供了几个计时器,大多数初学者都不清楚他们有什么不同,那我们这节来剖解一下每个计时器的本质:

1.System.Threading.Timer

如果在一个线程池上执行一个定时的周期性的后台线程任务他是最好的选择,这个类是和线程池相关联的,它告诉线程池(ThreadPool)在指定的时间执行指定的方法

2.System.Timers.Timer

这个类是对System.Threading.Timer类的封装,所以他两本质上是相同,在这里推荐使用System.Threading.Timer计时器

3.System.Windows.Forms.Timer

这个计时器经常和Window窗体一块使用,而且这个单线程处理的,从放入消息队列,再到提取,执行回调,都是一个线程完成

4.Windows.UI.Xaml.DispatcherTimer

这个类的本质就是System.Windows.Forms.Timer,微软设计目的是被用在Windows Store

5.System.Windows.Threading.DispatcherTimer

这个类和System.Windows.Forms.Timer本质是相同的,但是这个类用在WPF中

我们以System.Threading.Timer为例来介绍一下,推荐大家在项目中用这个计时器。

df9234addb58b078a1669269e35c42b7.png

我们可以看出有4个构造函数,我们分别讲解一下每个参数的用途

1、callback表示由线程池线程回调的方法,他是一个委托定义如下:

public delegate void TimerCallback(object state);

2、state 参数表示每次调用回调方法时传递的参数,如果没有则为null

3、dueTime表示在调用回调方法之前等待多少毫秒

4、period表示调用callback的时间间隔

我们在做开发的时候会遇到一种场景,当我们一个回调方法执行时间>period 设置的时间,就会导致上一个方法没有执行完,线程池就会新启动一个线程执行相同的方法,这样会产生多个线程同时执行一个方法,如何解决呢?我们可以在初始化Timer的时候给period参数设置为Timeout.Infinite,在回调方法中再次调用Timer.Change(3000,Timeout.Infinite) 并把peroid参数再次设置为Timeout.Infinite,下面代码我们对Timer进行了简单封装:

public class SafeTimer : IDisposable
{#region Fieldsprivate Timer innerTimer;private TimerCallback safeCallback = null!;private TimerCallback originalCallback = null!;private int syncPoint;private ManualResetEvent originalCallbackCompleteEvent = new ManualResetEvent(true);#endregion#region Constructorspublic SafeTimer(TimerCallback callback){InitializeCallback(callback);innerTimer = new Timer(safeCallback);}public SafeTimer(TimerCallback callback, object state, long dueTime, long period){InitializeCallback(callback);innerTimer = new Timer(safeCallback, state, dueTime, period);}public SafeTimer(TimerCallback callback, object state, uint dueTime, uint period){InitializeCallback(callback);innerTimer = new Timer(safeCallback, state, dueTime, period);}public SafeTimer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period){InitializeCallback(callback);innerTimer = new Timer(safeCallback, state, dueTime, period);}public SafeTimer(TimerCallback callback, object state, int dueTime, int period){InitializeCallback(callback);innerTimer = new Timer(safeCallback, state, dueTime, period);}#endregion#region Private methodsprivate void InitializeCallback(TimerCallback callback){originalCallback = callback;safeCallback = new TimerCallback(NonReentryCallback);}private void NonReentryCallback(object? state){//set syncPoint to 1 if the original value is 0. syncPoint=1 indicates a method is executing.if (Interlocked.CompareExchange(ref syncPoint, 1, 0) == 0){originalCallbackCompleteEvent.Reset();try{originalCallback(state);}catch { }finally{originalCallbackCompleteEvent.Set();Interlocked.Exchange(ref syncPoint, 0);}}}#endregion#region Public methodspublic bool Change(long dueTime, long period){return innerTimer.Change(dueTime, period);}public bool Change(int dueTime, int period){return innerTimer.Change(dueTime, period);}public bool Change(TimeSpan dueTime, TimeSpan period){return innerTimer.Change(dueTime, period);}public bool Change(uint dueTime, uint period){return innerTimer.Change(dueTime, period);}public void Stop(){innerTimer.Change(Timeout.Infinite, Timeout.Infinite);originalCallbackCompleteEvent.WaitOne();}public bool Stop(int milliseconds){innerTimer.Change(Timeout.Infinite, Timeout.Infinite);return originalCallbackCompleteEvent.WaitOne(milliseconds);}#endregion#region IDisposable Memberspublic void Dispose(){innerTimer.Dispose();}#endregion
}

我们做个简单的Demo来做个测试:

internal class Program
{private static SafeTimer safeTimer = null!;static void Main(string[] args){safeTimer = new SafeTimer(WriteLine, string.Empty, 2000, Timeout.Infinite);Console.ReadLine();}public static void WriteLine(object? state){Thread.Sleep(3000);Console.WriteLine("Hello " +DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff"));safeTimer.Change(2000, Timeout.Infinite);}
}

运行结果如下:

b07b53fedda80494c5aee750f7da8cd6.png

我们看到执行是按照线性执行,没有并行执行,达到我们预期效果,本质上是将任务调用ThreadPool.QueueUserWorkItem将任务放到线程池中执行!这节就到这里,希望对各位有收获。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/279806.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在.NET中不安装Office使用EPPlus生成带图表(Chart)的Excel报表

在开发.NET应用中可能会遇到需要生成带图表(Chart)的Excel报表的需求,特别是在一些ASP.NET网站中,有时候我们并不能保证Web服务器上一定安装了Office组件,所以使用微软的Office来生成Excel并不保证在所有情况下都使用,有时候即使W…

facebook 邀请好友_如何在Facebook上与某人解除好友

facebook 邀请好友It’s very easy for your Facebook News Feed to get cluttered. After a few years adding ukulele playing magicians you meet wandering the street and the bar staff at every bar you go to regularly, it gets overrun with people you’ll never se…

mac下npm/node的安装和卸载、升级;node、npm升级后最后删掉node_modules重新安装

mac还是使用brew install简单一些;最好使用一种安装方式,不要多种方式互用; 更新npm到最新版本npm install -g npm更新npm到指定版本 npm -g install npm2.9.1指定安装目录npm install --prefix /usr/local -g npm 1、从官网https://nodejs.o…

Edison的2022年终总结

大家好,我是Edison。2022年即将结束,又到了做年终总结的时候,它是我每年的一个习惯,意味着又要开始新的征途,在开始新的征途之前回顾一下很有必要。艰难抉择:从互联网到制造业今年最大的变化就是又换了份工…

JNI

配置NDK,调用JNI最终会生成一个so库,如果so库生成了。直接在项目中使用so库即可调用本地方法。注意:api的包名要与so库定义的包名一致。 1什么是jni jni java native interface java本地开发接口,是JAVA和C互相调用的桥梁。 2jni有…

dvd vlc 复制_如何使用VLC翻录DVD

dvd vlc 复制There are many ways to rip a DVD to your computer, but if you’re looking for the most straightforward option, VLC is easy and free. Besides, you probably already have VLC on your computer (and if you don’t, you should). Here, we’ll show you …

新年芯事 | 龙芯物联网主控芯片龙芯1C102和龙芯1C103流片成功

前言近期,龙芯中科面向物联网领域研制的主控芯片--龙芯1C102和龙芯1C103流片成功,两款微控制器芯片各项功能测试正常,符合设计预期。 龙芯1C102主要面向智能家居以及其他物联网设备详细介绍龙芯1C102采用龙芯LA132处理器核心,是一…

【加更】搭建基于chatgpt的钉钉聊天机器人

应某些小伙伴的加更请求,出一期基于钉钉上的聊天机器人,我顺便加更一期,搭建一个钉钉聊天机器人的小教程。首先进入到钉钉开放平台的后台管理系统:https://open.dingtalk.com/进入到 应用开发->企业内部开发->机器人右上角选…

word中 有注释标签吗_如何在Word中注释图像

word中 有注释标签吗If you’re writing a document that includes images, you may want to add annotations to those images to clarify what they represent. You can add callouts to your images to point out particular parts of the image and add text to describe t…

牛客网暑期ACM多校训练营(第二场)J farm (二维树状数组)

题目链接&#xff1a; https://www.nowcoder.com/acm/contest/140/J 思路&#xff1a; 都写在代码注释里了&#xff0c;非常好懂。。 for_each函数可以去看一下&#xff0c;遍历起vector数组比较方便&#xff0c;用for(int i 0;i < q[i].size();i)的话&#xff0c;是会有一…

微软IE 9 Beta全程体验图集

微软刚刚更新了IE 9 Beta的新页面&#xff0c;此次发布的Beta版本一共有27个国家的语言&#xff0c;其中也包括了简体中文和香港和台湾的繁体中文版。 点击此处进入下载页面&#xff1a; http://windows.microsoft.com/zh-CN/internet-explorer/download/ie-9/worldwide IE9的热…

.net core中Quartz的使用方法

我们在日常开发中&#xff0c;总会遇到这样的需求&#xff1a;每隔一段时间&#xff0c;执行一次某个任务。固定某个时间执行任务&#xff0c;例如凌晨12点对当天的数据进行统计。每个月的第几天&#xff0c;执行某个任务。Quartz.Net是根据Java的Quartz用C#改写而来&#xff0…

windows10访客_如何在Windows 10中创建访客帐户

windows10访客If you find that your guests are asking fairly often to use your computer temporarily to check their email or look something up on the web, you don’t have to let them use your personal account or create a special account for each guest. 如果发…

几个有趣的算法题目

本文首发 http://svtter.cn最接近的数字 题目 一个K位的数N $$ (K\leq2000&#xff0c;N\leq10^{20}) $$ 找出一个比N大且最接近的数&#xff0c;这个数的每位之和与N相同&#xff0c;用代码实现之。 例如&#xff1a;0050 所求书数字为0104&#xff1b;112 所求数为121&#x…

获取一篇新闻的全部信息

给定一篇新闻的链接newsUrl&#xff0c;获取该新闻的全部信息 标题、作者、发布单位、审核、来源 发布时间:转换成datetime类型 点击&#xff1a; newsUrlnewsId(使用正则表达式re)clickUrl(str.format(newsId))requests.get(clickUrl)newClick(用字符串处理&#xff0c;或正则…

上twitter_如何在Twitter上更改您的显示名称

上twitterUnlike Facebook, Twitter has never insisted people user their real names. In fact, there’s a long tradition of people changing their names to a joke or pun because it’s Christmas or Halloween, or just for no reason at all. 与Facebook不同&#xf…

网桥

配置实现网桥 网桥&#xff1a;即桥接 把一套机器上的若干个网络接口 “连接” 起来&#xff0c;其结果是&#xff0c;其中一个网口收到的报文会被复制给其他网口并发送出去。以使得网口之间的报文能够互相转发。网桥就是这样一个设备&#xff0c;它有若干个网口&#xff0c;并…

raspberry pi_在月光下将Raspberry Pi变成蒸汽机

raspberry piValve’s Steam Machines aim to bring your Steam game library right into your living room (but at a rather steep premium). Today we’ll show you how to bring your Steam library (plus all your other computer games) to your living room for a fract…

MySql数据库出现 1396错误

1、安装MySql数据库后。创建新的用户。有可能会出现 1396这个错误&#xff0c; 2、解决的办法如下&#xff1a;假装有你需要创建的这个用户、先删了。再创建。 3、这样就可以解决用户创建不成功的问题了。 转载于:https://www.cnblogs.com/chifa/p/9362882.html

如何使用wink框架_如何解决Wink Hub的Z-Wave连接问题

如何使用wink框架Overall, the Wink hub works extremely well…but sometimes the devices you have connected to it can act a little wonky. Here are some things you can do in order to fix any connection issues with all of those Z-Wave sensors and devices connec…