特定日期和时间的 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() 两个字符串(fridayPatternthursdayPattern)都在这里,然后找到哪个 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();

或者您可以选择动作并将其放入某个队列中,然后使用单独的线程同步或异步执行它们。那样的话,就没有机会错过第二名。