Vim*_*987 72 c# methods scheduled-tasks winforms
我搜索了SO并找到了关于Quartz.net的答案.但它似乎对我的项目来说太大了.我想要一个等效的解决方案,但更简单和(最好)代码内(不需要外部库).如何在特定时间每天调用一种方法?
我需要添加一些关于此的信息:
我想要一种更有效的方法来做到这一点,不需要经常检查时间,并且我可以控制是否完成了工作.如果方法失败(由于任何问题),程序应该知道写入日志/发送电子邮件.这就是我需要调用方法而不是安排工作的原因.
我发现这个解决方案在Java中用Java定时调用一个方法.在C#中是否有类似的方式?
编辑:我做到了这一点.我在void Main()中添加了一个参数,并创建了一个bat(由Windows Task Scheduler安排)以使用此参数运行程序.程序运行,完成工作,然后退出.如果作业失败,则能够写入日志和发送电子邮件.这种方法很符合我的要求:)
mar*_*c_s 74
这真的是你所需要的!
更新:如果您想在应用内执行此操作,您有以下几种选择:
Application.Idle事件并检查是否已达到当天的时间来调用您的方法.仅当您的应用不忙于其他内容时才会调用此方法.快速检查你的目标时间是否已经达到,不应该给你的应用带来太多压力,我认为...更新#2:如果你想每60分钟检查一次,你可以创建一个每60分钟唤醒一次的计时器,如果时间到了,它会调用该方法.
像这样的东西:
using System.Timers;
const double interval60Minutes = 60 * 60 * 1000; // milliseconds to one hour
Timer checkForTime = new Timer(interval60Minutes);
checkForTime.Elapsed += new ElapsedEventHandler(checkForTime_Elapsed);
checkForTime.Enabled = true;
Run Code Online (Sandbox Code Playgroud)
然后在你的事件处理程序中:
void checkForTime_Elapsed(object sender, ElapsedEventArgs e)
{
if (timeIsReady())
{
SendEmail();
}
}
Run Code Online (Sandbox Code Playgroud)
我创建了一个易于使用的简单调度程序,您不需要使用外部库.TaskScheduler是一个单例,可以对定时器进行引用,因此定时器不会被垃圾回收,它可以安排多个任务.您可以设置第一次运行(小时和分钟),如果在调度时此时间超过了当时的第二天的调度开始.但是自定义代码很容易.
安排新任务非常简单.示例:在11:52,第一个任务是每15个secunds,第二个例子是每5个secunds.对于每日执行,将24设置为3参数.
TaskScheduler.Instance.ScheduleTask(11, 52, 0.00417,
() =>
{
Debug.WriteLine("task1: " + DateTime.Now);
//here write the code that you want to schedule
});
TaskScheduler.Instance.ScheduleTask(11, 52, 0.00139,
() =>
{
Debug.WriteLine("task2: " + DateTime.Now);
//here write the code that you want to schedule
});
Run Code Online (Sandbox Code Playgroud)
我的调试窗口:
task2: 07.06.2017 11:52:00
task1: 07.06.2017 11:52:00
task2: 07.06.2017 11:52:05
task2: 07.06.2017 11:52:10
task1: 07.06.2017 11:52:15
task2: 07.06.2017 11:52:15
task2: 07.06.2017 11:52:20
task2: 07.06.2017 11:52:25
...
Run Code Online (Sandbox Code Playgroud)
只需将此类添加到您的项目中:
public class TaskScheduler
{
private static TaskScheduler _instance;
private List<Timer> timers = new List<Timer>();
private TaskScheduler() { }
public static TaskScheduler Instance => _instance ?? (_instance = new TaskScheduler());
public void ScheduleTask(int hour, int min, double intervalInHour, Action task)
{
DateTime now = DateTime.Now;
DateTime firstRun = new DateTime(now.Year, now.Month, now.Day, hour, min, 0, 0);
if (now > firstRun)
{
firstRun = firstRun.AddDays(1);
}
TimeSpan timeToGo = firstRun - now;
if (timeToGo <= TimeSpan.Zero)
{
timeToGo = TimeSpan.Zero;
}
var timer = new Timer(x =>
{
task.Invoke();
}, null, timeToGo, TimeSpan.FromHours(intervalInHour));
timers.Add(timer);
}
}
Run Code Online (Sandbox Code Playgroud)
正如其他人所说,您可以使用控制台应用程序在计划时运行.其他人没有说的是你可以在这个应用程序中触发你在主应用程序中等待的跨进程EventWaitHandle.
控制台应用:
class Program
{
static void Main(string[] args)
{
EventWaitHandle handle =
new EventWaitHandle(true, EventResetMode.ManualReset, "GoodMutexName");
handle.Set();
}
}
Run Code Online (Sandbox Code Playgroud)
主要应用:
private void Form1_Load(object sender, EventArgs e)
{
// Background thread, will die with application
ThreadPool.QueueUserWorkItem((dumby) => EmailWait());
}
private void EmailWait()
{
EventWaitHandle handle =
new EventWaitHandle(false, EventResetMode.ManualReset, "GoodMutexName");
while (true)
{
handle.WaitOne();
SendEmail();
handle.Reset();
}
}
Run Code Online (Sandbox Code Playgroud)
这是使用 TPL 执行此操作的方法。无需创建/处置计时器等:
void ScheduleSomething()
{
var runAt = DateTime.Today + TimeSpan.FromHours(16);
if (runAt <= DateTime.Now)
{
DoSomething();
}
else
{
var delay = runAt - DateTime.Now;
System.Threading.Tasks.Task.Delay(delay).ContinueWith(_ => DoSomething());
}
}
void DoSomething()
{
// do somethig
}
Run Code Online (Sandbox Code Playgroud)