如何在 C# 中每天在特定时间调用一个方法?
我搜索过 SO 并找到了有关 Quartz.net 的答案。但对于我的项目来说似乎太大了。我想要一个等效的解决方案,但更简单并且(最多)在代码中(不需要外部库)。如何每天在特定时间调用一个方法?
我需要添加一些关于此的信息:
- 最简单(且丑陋)的方法是每秒/每分钟检查一次时间并调用该方法,在正确的时间
我想要一种更有效的方法来执行此操作,无需不断地检查时间,我可以控制工作是否完成。如果该方法失败(由于任何问题),程序应该知道写入日志/发送电子邮件。这就是为什么我需要调用一个方法,而不是安排一个工作。
我找到了这个解决方案在Java中的固定时间调用方法在爪哇。 C#中有类似的方法吗?
编辑:我已经做到了。我在 void Main() 中添加了一个参数,并创建了一个 bat(由 Windows 任务计划程序调度)来使用该参数运行程序。程序运行,完成工作,然后退出。如果作业失败,它可以写入日志并发送电子邮件。这个方法很符合我的要求:)
I've searched on SO and found answers about Quartz.net. But it seems to be too big for my project. I want an equivalent solution, but simpler and (at best) in-code (no external library required). How can I call a method daily, at a specific time?
I need to add some information about this:
- the simplest (and ugly) way to do this, is check the time every second/minute and call the method, at right time
I want a more-effective way to do this, no need to check the time constantly, and I have control about whether the job is done a not. If the method fails (because of any problems), the program should know to write to log/send a email. That's why I need to call a method, not schedule a job.
I found this solution Call a method at fixed time in Java in Java. Is there a similar way in C#?
EDIT: I've done this. I added a parameter into void Main(), and created a bat (scheduled by Windows Task Scheduler) to run the program with this parameter. The program runs, does the job, and then exits. If a job fails, it's capable of writing log and sending email. This approach fits my requirements well :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(19)
这确实是您所需要的!
更新:如果您想在应用程序中执行此操作,您有多种选择:
Application.Idle
事件并检查以查看您是否已经到了一天中调用您的方法的时间。仅当您的应用程序不忙于其他事情时才会调用此方法。快速检查是否已达到目标时间不应给您的应用程序带来太大压力,我认为...更新 #2:如果您想每 60 分钟检查一次,您可以创建一个每 60 分钟唤醒一次的计时器,如果时间到了,它会调用该方法。
像这样:
然后在你的事件处理程序中:
That's really all you need!
Update: if you want to do this inside your app, you have several options:
Application.Idle
event and check to see whether you've reached the time in the day to call your method. This method is only called when your app isn't busy with other stuff. A quick check to see if your target time has been reached shouldn't put too much stress on your app, I think...Update #2: if you want to check every 60 minutes, you could create a timer that wakes up every 60 minutes and if the time is up, it calls the method.
Something like this:
and then in your event handler:
我创建了一个简单的调度程序,易于使用,您不需要使用外部库。 TaskScheduler 是一个单例,它保留对计时器的引用,因此计时器不会被垃圾收集,它可以调度多个任务。您可以设置第一次运行(小时和分钟),如果在安排时该时间已结束,则安排在第二天此时开始。但自定义代码很容易。
安排新任务是如此简单。示例:在 11:52,第一个任务每 15 秒执行一次,第二个示例每 5 秒执行一次。对于日常执行,将 24 设置为 3 参数。
我的调试窗口:
只需将此类添加到您的项目中:
I created a simple scheduler that is easy to use and you do not need to use external library. TaskScheduler is a singleton that keeps references on the timers so timers will not be garbage collected, it can schedule multiple tasks. You can set the first run (hour and minute), if at the time of scheduling this time is over scheduling start on the next day this at that time. But it is easy to customize the code.
Scheduling a new task is so simple. Example: At 11:52 the first task is for every 15 secunds, the second example is for every 5 secunds. For daily execution set 24 to the 3 parameter.
My debug window:
Just add this class to your project:
每当我构建需要此类功能的应用程序时,我总是通过我找到的一个简单的 .NET 库来使用 Windows 任务计划程序。
请请参阅我对类似问题的回答获取一些示例代码和更多说明。
Whenever I build applications that require such functionality, I always use the Windows Task Scheduler through a simple .NET library that I found.
Please see my answer to a similar question for some sample code and more explanation.
正如其他人所说,您可以使用控制台应用程序按计划运行。其他人没有说的是,您可以此应用程序触发您在主应用程序中等待的跨进程 EventWaitHandle。
控制台应用程序:
主应用程序:
As others have said you can use a console app to run when scheduled. What others haven't said is that you can this app trigger a cross process EventWaitHandle which you are waiting on in your main application.
Console App:
Main App:
这是使用 TPL 执行此操作的方法。无需创建/处置计时器等:
Here's a way to do this using TPL. No need to create/dispose of a timer, etc:
据我所知,最好的方法(可能也是最简单的方法)是使用 Windows 任务计划程序在一天中的特定时间执行代码,或者让应用程序永久运行并检查一天中的特定时间,或者编写一个执行以下操作的 Windows 服务:相同的。
The best method that I know of and probably the simplest is to use the Windows Task Scheduler to execute your code at a specific time of day or have you application run permanently and check for a particular time of day or write a windows service that does the same.
我知道这很旧,但是这样怎么样:
构建一个在启动时触发的计时器,计算下次运行时间的时间。在第一次调用运行时时,取消第一个计时器并启动新的每日计时器。将每日更改为每小时或任何您想要的周期。
I know this is old but how about this:
Build a timer to fire at startup that calculates time to next run time. At the first call of the runtime, cancel the first timer and start a new daily timer. change daily to hourly or whatever you want the periodicity to be.
这个小程序应该是解决方案;-)
我希望这对每个人都有帮助。
This little program should be the solution ;-)
I hope this helps everyone.
我最近刚刚编写了必须每天重新启动的 ac# 应用程序。我意识到这个问题已经很老了,但我认为添加另一个可能的解决方案并没有什么坏处。这就是我处理每日在指定时间重新启动的方式。
为了确保您的计时器保持在范围内,我建议使用 System.Timers.Timer tmrRestart = new System.Timers.Timer() 方法在方法之外创建它。将方法
RestartApp()
放入表单加载事件中。当应用程序启动时,如果current
大于重启时间,它将设置AppRestart
的值,我们在AppRestart
上添加 1 天以确保重启准时发生,并且我们不会因将负值放入计时器而出现异常。在 tmrRestart_Elapsed 事件中运行您需要在该特定时间运行的任何代码。如果您的应用程序自行重新启动,您不一定需要停止计时器,但这也没有什么坏处,如果应用程序没有重新启动,只需再次调用RestartApp()
方法即可很好,可以走了。I just recently wrote a c# app that had to restart daily. I realize this question is old but I don't think it hurts to add another possible solution. This is how I handled daily restarts at a specified time.
To ensure your timer is kept in scope I recommend creating it outside of the method using
System.Timers.Timer tmrRestart = new System.Timers.Timer()
method. Put the methodRestartApp()
in your form load event. When the application launches it will set the values forAppRestart
ifcurrent
is greater than the restart time we add 1 day toAppRestart
to ensure the restart happens on time and that we don't get an exception for putting a negative value into the timer. In thetmrRestart_Elapsed
event run whatever code you need ran at that specific time. If your application restarts on it's own you don't necessarily have to stop the timer but it doesn't hurt either, If the application does not restart simply call theRestartApp()
method again and you will be good to go.我发现这非常有用:
I found this very useful:
3线怎么样?
How about a 3 liner?
如果您想要运行可执行文件,请使用 Windows 计划任务。我将假设(可能是错误的)您想要一个方法在当前程序中运行。
为什么不让一个连续运行的线程存储调用该方法的最后日期呢?
让它每分钟唤醒一次(例如),如果当前时间大于指定时间并且最后存储的日期不是当前日期,则调用该方法然后更新日期。
If you want an executable to run, use Windows Scheduled Tasks. I'm going to assume (perhaps erroneously) that you want a method to run in your current program.
Why not just have a thread running continuously storing the last date that the method was called?
Have it wake up every minute (for example) and, if the current time is greater than the specified time and the last date stored is not the current date, call the method then update the date.
您可以计算剩余时间并将计时器设置为该时间的一半(或其他分数),而不是设置每 60 分钟每秒运行一次的时间。这样,您就不必过多地检查时间,但也可以保持一定程度的准确性,因为计时器间隔会随着您距离目标时间的距离而减少。
例如,如果您想在 60 分钟后执行某项操作,则计时器间隔约为:
30:00:00、15:00:00、07:30:00、03:45:00、...、00:00 :01,跑!
我使用下面的代码每天自动重新启动一次服务。我使用线程是因为我发现计时器在很长一段时间内不可靠,虽然在本例中成本更高,但它是为此目的创建的唯一一个,所以这并不重要。
(从 VB.NET 转换)
...
注意我设置了 1000 毫秒的最小间隔,可以根据您需要的精度增加、减少或删除该间隔。
请记住,当您的应用程序关闭时,也要停止您的线程/计时器。
Rather than setting a time to run every second of every 60 minutes you can calculate the time remaining and set the timer to half (or some other fraction) of this. This way your not checking the time as much but also maintianing a degree of accurcy as the timer interval reduces the closer you get to your target time.
For example if you wanted to do something 60 minutes from now the timers intervals would be aproximatly:
30:00:00, 15:00:00, 07:30:00, 03:45:00, ... , 00:00:01, RUN!
I use the code below to automatically restart a service once a day. I use a thread becuase I have found timers to be unreliable over long periods, while this is more costly in this example it is the only one created for this purpose so this dosn't matter.
(Converted from VB.NET)
...
Note I have set a mininum interval of 1000 ms, this could be increaded, reduced or removed depending upon the accurcy you require.
Remember to also stop your thread/timer when your application closes.
我对此有一个简单的方法。这会在操作发生之前造成 1 分钟的延迟。您也可以添加秒数来使 Thread.Sleep();更短。
I have a simple approach to this. This creates a 1 minute delay before the action happens. You could add seconds as well to make the Thread.Sleep(); shorter.
可能只是我的问题,但似乎大多数答案都不完整或无法正常工作。我做了一些又快又脏的东西。话虽这么说,不确定这样做有多好,但每次都很完美。
It may just be me but it seemed like most of these answers were not complete or would not work correctly. I made something very quick and dirty. That being said not sure how good of an idea it is to do it this way, but it works perfectly every time.
24小时时间
24 hours times
尝试使用 Windows 任务计划程序。创建一个不提示任何用户输入的 exe。
https://learn.microsoft.com/ en-us/windows/win32/taskschd/task-scheduler-start-page
Try to use Windows Task Scheduler. Create an exe which is not prompting for any user inputs.
https://learn.microsoft.com/en-us/windows/win32/taskschd/task-scheduler-start-page
一项任务的简单示例:
A simple example for one task:
System.Threading.Timer 的解决方案:
Solution with System.Threading.Timer: