是否有任何聪明的方法可以让我的executeEveryDayMethod()每天执行一次,而不必涉及Windows TaskScheduler?
此致
/安德斯
答案 0 :(得分:16)
我通过以下方式实现了这一目标......
HTH
*编辑 - C#中的代码示例::注意:未经测试...
using System;
using System.Collections.Generic;
using System.Text;
using System.Timers;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Timer t1 = new Timer();
t1.Interval = (1000 * 60 * 20); // 20 minutes...
t1.Elapsed += new ElapsedEventHandler(t1_Elapsed);
t1.AutoReset = true;
t1.Start();
Console.ReadLine();
}
static void t1_Elapsed(object sender, ElapsedEventArgs e)
{
DateTime scheduledRun = DateTime.Today.AddHours(3); // runs today at 3am.
System.IO.FileInfo lastTime = new System.IO.FileInfo(@"C:\lastRunTime.txt");
DateTime lastRan = lastTime.LastWriteTime;
if (DateTime.Now > scheduledRun)
{
TimeSpan sinceLastRun = DateTime.Now - lastRan;
if (sinceLastRun.Hours > 23)
{
doStuff();
// Don't forget to update the file modification date here!!!
}
}
}
static void doStuff()
{
Console.WriteLine("Running the method!");
}
}
}
答案 1 :(得分:8)
看看quartz.net。它是.net的调度库。
更具体地看一下here。
答案 2 :(得分:4)
如果它运行的时间不相关,并且每次程序启动时都可以重置,你可以设置一个计时器,这是最简单的事情。如果这是不可接受的,它开始变得越来越复杂,就像所提出的解决方案here并且仍然无法解决持久性问题,如果您真的希望执行计划任务,那么您需要单独解决这个问题。我真的会再次考虑是否值得通过所有麻烦来复制完美的现有功能。
这是一个related question(从那里取的例子)。
using System;
using System.Timers;
public class Timer1
{
private static Timer aTimer = new System.Timers.Timer(24*60*60*1000);
public static void Main()
{
aTimer.Elapsed += new ElapsedEventHandler(ExecuteEveryDayMethod);
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
}
// Specify what you want to happen when the Elapsed event is
// raised.
private static void ExecuteEveryDayMethod(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
}
答案 3 :(得分:0)
你可以在一段时间内查询时间并运行,即使机器熄火,你也可以调用方法或使用类似Vinko建议的计时器。
但是更好的解决方案(类似于旧的CRON版本,因此它是一个经过验证的模式)是拥有一些持久性数据,我现在可以想到的最便宜的解决方案是空白文件,检查其最后修改的属性,以及是否它在最近24小时内没有被修改,你触摸它并运行你的方法。这样,您可以确保方法在应用程序周末出现的情况下首先运行。例如。
我之前在C#中做过这个,但是它是一年前在另一个Job上做的,所以我没有代码,但它大约有20行(带有注释和所有)左右。
答案 4 :(得分:0)
如果计算机重新启动可能会出现问题,因此您可以将应用程序作为Windows服务运行。
答案 5 :(得分:0)
要在7到8pm之间每天运行一次作业,我设置了一个间隔= 3600000 ms的计时器,然后执行以下代码进行计时器滴答。
private void timer1_Tick(object sender, EventArgs e)
{
//ensure that it is running between 7-8pm daily.
if (DateTime.Now.Hour == 19)
{
RunJob();
}
}
小时窗口对我来说很好。时间上的额外粒度将需要较小的计时器间隔(60000一分钟),并包括if的分钟。
例如
{
//ensure that it is running at 7:30pm daily.
if (DateTime.Now.Hour == 19 && DateTime.Now.Minute == 30)
{
RunJob();
}
}
答案 6 :(得分:0)
如果您只想每天运行一次,而不关心何时运行,那么它将起作用(将在午夜之后运行)。
声明一个DateTime
变量:
DateTime _DateLastRun;
在启动时,设置初始日期值:
_DateLastRun = DateTime.Now.Date;
在要检查是否执行操作的逻辑区域中:
if (_DateLastRun < DateTime.Now.Date)
{
// Perform your action
_DateLastRun= DateTime.Now.Date;
}
答案 7 :(得分:0)
公共局部类Main:形式
{
public Main()// Windows窗体称为Main
{
InitializeComponent();
}
private void Main_Load( object sender, EventArgs e )
{
/*
This example uses a System.Windows.Forms Timer
This code allows you to schedule an event at any given time in one day.
In this example the timer will tick at 3AM.
*/
Int32 alarm = GetAlarmInMilliseconds( 3, 0, 0 ); // Milliseconds until 3:00 am.
timer_MessageCount.Interval = alarm; // Timer will tick at 3:00am.
timer_MessageCount.Start( );
}
private Int32 GetAlarmInMilliseconds(Int32 eventHour, Int32 eventMinute, Int32 eventSecond )
{
DateTime now = DateTime.Now;
DateTime eventTime = new DateTime( now.Year, now.Month, now.Day, eventHour, eventMinute, eventSecond );
TimeSpan ts;
if ( eventTime > now )
{
ts = eventTime - now;
}
else
{
eventTime = eventTime.AddDays( 1 );
ts = eventTime - now;
}
Console.WriteLine("Next alarm in: {0}", ts );
return ( Int32 ) ts.TotalMilliseconds;
}
static void DoSomething( )
{
Console.WriteLine( "Run your code here." );
}
private void timer_MessageCount_Tick( object sender, EventArgs e )
{
DoSomething( );
Int32 alarm = GetAlarmInMilliseconds( 3, 0, 0 ); // Next alarm time = 3AM
timer_MessageCount.Interval = alarm;
}
}
答案 8 :(得分:0)
您可以尝试此解决方案。
public Main()
{
StartService();
}
public async Task StartService(CancellationToken token = default(CancellationToken))
{
while (!token.IsCancellationRequested)
{
ExecuteFunction();
try
{
await Task.Delay(TimeSpan.FromDays(1), token);
}
catch (TaskCanceledException)
{
break;
}
}
}
public async Task ExecuteFunction()
{
...
}
答案 9 :(得分:0)
如果您正在运行Windows Forms应用程序,则可以按以下方法进行操作。但是,您需要配置一个设置,以便可以存储触发事件的最后日期。如果您从不打算关闭应用程序,则可以将日期存储为静态值。
我正在使用计时器来触发事件,如下所示:
private void tmrAutoBAK_Tick(object sender, EventArgs e)
{
if (BakDB.Properties.Settings.Default.lastFireDate != DateTime.Now.ToString("yyyy-MM-dd"))
{
tmrAutoBAK.Stop(); //STOPS THE TIMER IN CASE OF EVENTUAL MESSAGEBOXES.
createBakup(); //EVENT
BakDB.Properties.Settings.Default.lastFireDate = DateTime.Now.ToString("yyyy-MM-dd"); //STORING CURRENT DATE TO SETTINGS FILE.
BakDB.Properties.Settings.Default.Save(); //SAVING THE SETTING FILE.
tmrAutoBAK.Start(); //RESTARTING TIMER
}
}