C# - System.Timers.Timer 的替代方案,在特定时间调用函数
我想在特定时间调用 C# 应用程序上的特定函数。起初我考虑使用 Timer
(System.Time.Timer),但很快就变得无法使用。为什么?
简单的。 Timer 类需要一个以毫秒为单位的 Interval
,但考虑到我可能希望执行该函数,假设在一周内,这意味着:
- 7 天 = 168 小时;
- 168 小时 = 10,080 分钟;
- 10,080 分钟 = 604,800 秒;
- 604,800 秒 = 604,800,000 毫秒;
- 所以间隔是 604,800,000;
现在让我们记住 Interval
接受的数据类型是 int
,并且我们知道 int
范围从 -2,147,483,648 到 2,147,483,647。
这使得Timer
毫无用处,不是在这种情况下,而是在超过大约25天的情况下,一旦我们无法将Interval
设置为大于2,147,483,647毫秒。< /strong>
所以我需要一个可以指定何时调用该函数的解决方案。 类似这样:
solution.ExecuteAt = "30-04-2010 15:10:00";
solution.Function = "functionName";
solution.Start();
因此,当系统时间达到“30-04-2010 15:10:00”时,该函数将在应用程序中执行。
如何解决这个问题?
其他信息:这些功能将做什么?
- 获取气候信息并基于该信息:
- 启动/关闭其他应用程序(大多数是控制台)基于);
- 向这些控制台应用程序发送自定义命令;
- 电脑断电、重启、睡眠、休眠;
- 如果可能的话,安排 BIOS 启动计算机;
编辑:
Interval
接受的数据类型似乎是 double< /code>,但是,如果您将
Interval
设置为大于 int
的值,并调用 Start()
,则会引发异常[0,Int32.MaxValue]
。
编辑 2:
Jørn Schou-Rode 建议使用 Ncron 来处理安排任务,乍一看这似乎是一个很好的解决方案,但我想听听一些使用过它的人的情况。
I want to call a specific function on my C# application at a specific time. At first I thought about using a Timer
(System.Time.Timer)
, but that soon became impossible to use. Why?
Simple. The Timer class requires a Interval
in milliseconds, but considering that I might want the function to be executed, let's says in a week that would mean:
- 7 days = 168 hours;
- 168 hours = 10,080 minutes;
- 10,080 minutes = 604,800 seconds;
- 604,800 seconds = 604,800,000 milliseconds;
- So the interval would be 604,800,000;
Now let's remember that the Interval
accepted data type is int
, and as we know int
range goes from -2,147,483,648 to 2,147,483,647.
That makes Timer
useless, not in this case, but in the case of more than about 25 days, once we cannot set a Interval
bigger that 2,147,483,647 milliseconds.
So I need a solution where I could specify when the function should be called. Something like this:
solution.ExecuteAt = "30-04-2010 15:10:00";
solution.Function = "functionName";
solution.Start();
So when the System Time would reach "30-04-2010 15:10:00" the function would be executed in the application.
How can this problem be solved?
Additional information: What will these functions do?
- Getting climate information and based on that information:
- Starting / Shutting down other applications (most of them console based);
- Sending custom commands to those console applications;
- Power down, rebooting, sleep, hibernate the computer;
- And if possible schedule the BIOS to power up the computer;
EDIT:
It would seem that the Interval
accepted data type is double
, however if you set a value bigger that an int
to the Interval
, and call Start()
it throws a exception [0, Int32.MaxValue]
.
EDIT 2:
Jørn Schou-Rode suggested using Ncron to handle the scheduling tasks, and at first look this seems a good solution, but I would like to hear about some who has worked with it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
您的“Start()”方法应该生成一个线程,该线程以定义的时间间隔唤醒,检查时间,如果没有达到所需的时间,则返回睡眠状态。
Your "Start()" method should spawn a thread that wakes up at a defined interval, checks the time, and if you haven't reached the desired time, goes back to sleep.
任务调度的一种方法与 klausbyskov 提出的方法类似,是在现有的 .NET 调度框架/库之上构建调度服务。与使用 Windows 任务计划程序相比,这具有以下优点:(a) 允许在同一项目中定义多个作业,以及 (b) 将作业和调度逻辑“在一起”,即不依赖于容易迷失的服务器设置。系统升级/更换。
我知道有两个开源项目提供这种功能:
"Quartz.NET 是一个功能齐全的开源作业调度系统,可用于从最小的应用程序到大型企业系统。”我自己从未真正使用过这个框架,但通过研究该网站,我的印象是一个非常可靠的工具,提供了许多很酷的功能。 Stackoverflow 上有
[quartz-net]
标签这一事实也可能表明它“NCron 是一个轻量级库,用于在.NET 服务器平台。”它的功能数量没有 Quartz.NET 的一半,而且在 Stackoverflow 上也没有任何标签,但作者(真正的作者)相信,它的低摩擦 API 使其更容易上手。
在 NCron 之上构建调度服务,您可以使用一行代码安排每周执行的
CleanupJob
:好的,您将需要在此之上大约三行样板代码实际上将您的项目变成 Windows 服务,但当我声称可以用一行代码完成它时,听起来更令人印象深刻;)
One approach to task scheduling, simliar to that proposed by klausbyskov, is to built your scheduling service on top of an existing .NET scheduling framework/library. Compared to using the Windows Task Scheduler, this has the advantages of (a) allowing several jobs to be defined in the same project and (b) keeping jobs and scheduling logic "together" - i.e. not relying on server settings prone to get lost in system upgrades/replacements.
I know of two open-source projects that offer this kind of functionality:
"Quartz.NET is a full-featured, open source job scheduling system that can be used from smallest apps to large scale enterprise systems." I have never actually used this framework myself, but from studying the website, I have the impression of a very solid tool, providing many cool features. The fact that there
[quartz-net]
tag on Stackoverflow might also indicate that it is actually used in the wild."NCron is a light-weight library for building and deploying scheduled background jobs on the .NET server platform." It does not have half as many features as Quartz.NET, and it does not have any tag on Stackoverflow, but the author (yours truly) believes that its low-friction API makes it somewhat easier to get started with.
Building your scheduling service on top of NCron, you can schedule a
CleanupJob
for weekly execution using a single line of code:Ok, you will need around three lines of boiler plate code on top of that to actually turn your project into a Windows service, but it sounds more impressive when I claim that it can be done with one line of code ;)
我建议您只编写一个处理其业务部分的程序,然后在必要时使用Windows 任务计划程序执行该程序。
I would recommend that you just write a program that deals with the business part of it and then execute that program when necessary by using Windows Task Scheduler.
您可以为带有 DateTime 实例的 Timer 编写某种包装类。然后执行以下步骤:
有时,差异将小于 Interval 属性的最大允许值,然后您可以在包装器中触发一个事件,该事件最终调用所需的方法。
You could write some sort of wrapper class for a Timer which takes a DateTime instance. Then you perform the following steps:
At some time, the difference will be smaller than the maximum allowed value for the Interval property, and then you could fire an event in your wrapper which ultimately calls the desired method.
使用 System.Threading.Timer:
Use the System.Threading.Timer:
您可以使用 System.Threading.Timer 类,它提供了一个接受以 Int64 表示的间隔的构造函数,这应该足以满足您的需求。
现在来说其他的事情:
You can use the
System.Threading.Timer
class, which provides a constructor accepting an interval expressed as an Int64, which should be enough for your needs.Now for the other stuff :
Process
class (I don't really get what you call "custom commands")System.Threading.Timer 类也有相同的限制(根据 MSDN)。
似乎没有 .Net Framework 类本身就擅长规避
Int32.MaxValue
毫秒上限。我使用的解决方案与上面的示例类似:一个类
Scheduler
管理所有Task
(为了避免我们为每个任务都有一个计时器)正在安排)。任务被添加到能够执行排序插入的队列中。请注意,SortedQueue不是 .Net Framework 的一种类型,而是一个假设的、易于编码的集合,能够在类似类型 T 上进行排序插入。
调度程序会唤醒每个 TimerGranularity 毫秒并检查第一个任务的“ExecuteAt”时间已被超过;然后在单独的线程上执行它。
可以通过创建所有超越任务的列表(而不仅仅是第一个任务)来完成额外的工作;但为了清楚起见,我省略了它。
The class
System.Threading.Timer
has the same limitation too (it would throw anArgumentOutOfRangeException
according to MSDN).There seems to be no .Net Framework class natively adept to circumvent the
Int32.MaxValue
milliseconds upper bound.The solution I'd use is something similar to the above example: a class
Scheduler
that manages all theTask
s (in order to avoid having a timer for each task we are going to schedule).Tasks are added to the a queue able to perform sorted insertion. Note that
SortedQueue<T>
is not a type of the .Net Framework but an hypothetical, easy-to-code collection capable of sorted insertion on a comparable type T.The scheduler awakes every
TimerGranularity
milliseconds and checks for the first task whose `ExecuteAt' time has been surpassed; then executes it on a separate thread.Additional effort could be done by creating a list of all surpassed tasks (instead of the first one only); but I left it out for the sake of clarity.
有一个名为 Quartz.NET 的 nu-get。
您完全可以将其用于此目的。
There is exist exist nu-get called Quartz.NET.
You can use it exactly for this.