特定日期和时间的 C# 操作
C# action on specific date and time
我正在尝试在一周中的给定日期的给定时间滚动时创建一个动作。
这是我目前的情况:
private void wbnotifier_CheckedChanged(object sender, EventArgs e)
{
if (DateTime.UtcNow.DayOfWeek == DayOfWeek.Friday)
MessageBox.Show ("It's Friday");
if (DateTime.UtcNow.DayOfWeek == DayOfWeek.Thursday)
MessageBox.Show("It's Thursday");
}
我如何安排才能在周五 1:00 下午和周四 5:00 下午触发操作?
在同一天多次出现类似情况吗? (星期五,1:00 下午,3:00 下午,6:00 下午)
这种语句很难自动化,你要么每天做一个switch case,要么每天每小时做一个switch case。另一种方法是存储 DateTime 列表,if (list.Any(x => x.DayOfWeek == DateTime.UtcNow.DayOfWeek && x.Hour == DateTime.UtcNow.Hour) doStuff()
您需要在线程或计时器中 运行 每 x 秒检查一次。
如果您想在 .NET 中安排事情,您应该查看 Quartz.net。这是 CronTrigger 的示例:
// Build a trigger that will fire on Wednesdays at 10:42 am, in a TimeZone other // than the system's default:
trigger = TriggerBuilder.Create()
.WithIdentity("trigger3", "group1")
.WithSchedule(CronScheduleBuilder
.WeeklyOnDayAndHourAndMinute(DayOfWeek.Wednesday, 10, 42)
.InTimeZone(TimeZoneInfo.FindSystemTimeZoneById("Central America Standard Time")))
.ForJob(myJobKey)
.Build();
看看 ncrontab 项目。
(您可以手动添加对您的解决方案的 DLL 引用或简单地 install it with NuGet。)
ncrontab 可以像您一样轻松配置任务。
在您的代码或 App.config 中,您只需定义一个由 5 部分组成的字符串:
* * * * *
- - - - -
| | | | |
| | | | +----- day of week (0 - 6) (Sunday=0)
| | | +------- month (1 - 12)
| | +--------- day of month (1 - 31)
| +----------- hour (0 - 23)
+------------- min (0 - 59)
为了让它更简单一点:是否可以同时启动两个任务?据我所知,不可能在同一模式中为每一天配置单独的时间。
string pattern = "* 17 * * 4,5";
如果这对您不切实际,您可以定义两种不同的模式,然后检查其中哪一种模式出现得更快。
在你的情况下,这可能是这样的:
// Friday 1 PM
string fridayPattern = "* 13 * * 5";
或
// Thursday 5 PM
string thursdayPattern = "* 17 * * 4";
解释模式的代码可能如下所示:
CrontabSchedule schedule = CrontabSchedule.Parse(pattern);
DateTime nextOccurrence = this.schedule.GetNextOccurrence(DateTime.Now);
TimeSpan interval = nextOccurrence.Subtract(now);
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = interval.TotalMilliseconds;
timer.Elapsed -= this.OnScheduleTimerElapsed;
timer.Elapsed += this.OnScheduleTimerElapsed;
timer.Start();
注意:
如果您使用 2 模式的想法,您将 CrontabSchedule.Parse()
两个字符串(fridayPattern
和 thursdayPattern
)都在这里,然后找到哪个 GetNextOccurrence()
会更快出现。
无论哪种方式,那么,当然,您都需要处理该事件:
private void OnScheduleTimerElapsed(object sender, ElapsedEventArgs e)
{
this.timer.Stop();
this.timer.Elapsed -= this.OnScheduleTimerElapsed;
// Start your work here.
}
你的第二个问题:
要在同一天配置多个运行,如下所示:
// Friday, 1:00 PM, 3:00 PM, 6:00 PM
string multipleRunsOnSameDayPattern = "* 13,15,18 * * 5"
对于每周定期通知,您可以使用如下内容
Dictionary<DayOfWeek, Dictionary<TimeSpan, Action>> recurringNotifications = new Dictionary<DayOfWeek, Dictionary<TimeSpan, Action>>();
recurringNotifications.Add(DayOfWeek.Friday, new Dictionary<TimeSpan, Action>(){ {TimeSpan.FromHours(1), () => Console.WriteLine("1 AM") }});
在你的计时器上,你可以做一些事情,比如
var todaysEvents = recurringNotifications[DateTime.UtcNow.DayOfWeek];
todaysEvents[TimeSpan.FromHours(1)].BeginInvoke();
或者您可以选择动作并将其放入某个队列中,然后使用单独的线程同步或异步执行它们。那样的话,就没有机会错过第二名。
我正在尝试在一周中的给定日期的给定时间滚动时创建一个动作。
这是我目前的情况:
private void wbnotifier_CheckedChanged(object sender, EventArgs e)
{
if (DateTime.UtcNow.DayOfWeek == DayOfWeek.Friday)
MessageBox.Show ("It's Friday");
if (DateTime.UtcNow.DayOfWeek == DayOfWeek.Thursday)
MessageBox.Show("It's Thursday");
}
我如何安排才能在周五 1:00 下午和周四 5:00 下午触发操作?
在同一天多次出现类似情况吗? (星期五,1:00 下午,3:00 下午,6:00 下午)
这种语句很难自动化,你要么每天做一个switch case,要么每天每小时做一个switch case。另一种方法是存储 DateTime 列表,if (list.Any(x => x.DayOfWeek == DateTime.UtcNow.DayOfWeek && x.Hour == DateTime.UtcNow.Hour) doStuff()
您需要在线程或计时器中 运行 每 x 秒检查一次。
如果您想在 .NET 中安排事情,您应该查看 Quartz.net。这是 CronTrigger 的示例:
// Build a trigger that will fire on Wednesdays at 10:42 am, in a TimeZone other // than the system's default:
trigger = TriggerBuilder.Create()
.WithIdentity("trigger3", "group1")
.WithSchedule(CronScheduleBuilder
.WeeklyOnDayAndHourAndMinute(DayOfWeek.Wednesday, 10, 42)
.InTimeZone(TimeZoneInfo.FindSystemTimeZoneById("Central America Standard Time")))
.ForJob(myJobKey)
.Build();
看看 ncrontab 项目。 (您可以手动添加对您的解决方案的 DLL 引用或简单地 install it with NuGet。)
ncrontab 可以像您一样轻松配置任务。 在您的代码或 App.config 中,您只需定义一个由 5 部分组成的字符串:
* * * * *
- - - - -
| | | | |
| | | | +----- day of week (0 - 6) (Sunday=0)
| | | +------- month (1 - 12)
| | +--------- day of month (1 - 31)
| +----------- hour (0 - 23)
+------------- min (0 - 59)
为了让它更简单一点:是否可以同时启动两个任务?据我所知,不可能在同一模式中为每一天配置单独的时间。
string pattern = "* 17 * * 4,5";
如果这对您不切实际,您可以定义两种不同的模式,然后检查其中哪一种模式出现得更快。
在你的情况下,这可能是这样的:
// Friday 1 PM
string fridayPattern = "* 13 * * 5";
或
// Thursday 5 PM
string thursdayPattern = "* 17 * * 4";
解释模式的代码可能如下所示:
CrontabSchedule schedule = CrontabSchedule.Parse(pattern);
DateTime nextOccurrence = this.schedule.GetNextOccurrence(DateTime.Now);
TimeSpan interval = nextOccurrence.Subtract(now);
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = interval.TotalMilliseconds;
timer.Elapsed -= this.OnScheduleTimerElapsed;
timer.Elapsed += this.OnScheduleTimerElapsed;
timer.Start();
注意:
如果您使用 2 模式的想法,您将 CrontabSchedule.Parse()
两个字符串(fridayPattern
和 thursdayPattern
)都在这里,然后找到哪个 GetNextOccurrence()
会更快出现。
无论哪种方式,那么,当然,您都需要处理该事件:
private void OnScheduleTimerElapsed(object sender, ElapsedEventArgs e)
{
this.timer.Stop();
this.timer.Elapsed -= this.OnScheduleTimerElapsed;
// Start your work here.
}
你的第二个问题:
要在同一天配置多个运行,如下所示:
// Friday, 1:00 PM, 3:00 PM, 6:00 PM
string multipleRunsOnSameDayPattern = "* 13,15,18 * * 5"
对于每周定期通知,您可以使用如下内容
Dictionary<DayOfWeek, Dictionary<TimeSpan, Action>> recurringNotifications = new Dictionary<DayOfWeek, Dictionary<TimeSpan, Action>>();
recurringNotifications.Add(DayOfWeek.Friday, new Dictionary<TimeSpan, Action>(){ {TimeSpan.FromHours(1), () => Console.WriteLine("1 AM") }});
在你的计时器上,你可以做一些事情,比如
var todaysEvents = recurringNotifications[DateTime.UtcNow.DayOfWeek];
todaysEvents[TimeSpan.FromHours(1)].BeginInvoke();
或者您可以选择动作并将其放入某个队列中,然后使用单独的线程同步或异步执行它们。那样的话,就没有机会错过第二名。