我想每天早上4点执行.exe。我使用以下代码完成了这项工作。
Directory.Delete(folder_path, recursive: true);
现在我想再执行一项任务,例如每晚凌晨1点删除特定文件夹和子文件夹。因此,对于删除,我将使用像
这样的代码{{1}}
我应该使用相同的无限循环还是以其他方式实现它?
答案 0 :(得分:4)
您不应该使用Thread.Sleep进行计时。尽量避免使用Thread.Sleep。如果中止该线程,则只能中断睡眠。更好的方法是ManualResetEvent.Wait()
可以通过设置来中断。
我的建议是,使用计时器:
创建一个正在检查作业列表的计时器。添加下一次在作业上执行。计时器不会阻止MainThread,因此您可以安全地终止该应用程序。您可以每分钟甚至更高的时间检查作业(间隔)。
<强>伪!! 强>
class MyJob
{
public DateTime ExecuteTime { get; set; }
public Action Action { get; set; }
}
List<MyJob> Jobs = new List<MyJob>();
public void TimerCallback(object sender, EventArgs e)
{
foreach (var job in Jobs)
{
if (job.ExecuteTime <= DateTime.Now)
{
try
{
job.Action();
}
catch(Exception exception)
{
// log the exception..
}
finally
{
job.ExecuteTime = job.ExecuteTime.Add(TimeSpan.FromDays(1));
}
}
}
}
// this AddJob checks if the first execute should be today or tomorrow
public void AddJob(TimeSpan executeOn, Action action)
{
var now = DateTime.Now;
var firstExec = new DateTime(now.Year, now.Month, now.Day, 4, 0, 0);
if (firstExec < now) // time for today is already passed, next day..
firstExec = firstExec.Add(TimeSpan.FromDays(1));
Jobs.Add(new MyJob { ExecuteTime = firstExec, Action = action });
}
public void Add()
{
// Add the jobs.
AddJob(new TimeSpan(4, 0, 0), RunMyJob);
AddJob(new TimeSpan(5, 0, 0), RunMyJob2);
}
public void RunMyJob()
{
// delete or move, whatever...
}
public void RunMyJob2()
{
// delete or move, whatever...
}
答案 1 :(得分:2)
如果你所做的只是安排单个.exe,你可以使用Windows任务计划程序 - 它比自己尝试自己要容易得多。如果您需要在几个不同的时间完成多个任务,则可以创建多个.exes。 (抱歉要简短,我是在电话上写的。)
答案 2 :(得分:2)
我会使用Microsoft的Reactive Framework(NuGet“System.Reactive”)。
然后你可以编写这个方便的助手方法:
public IDisposable ScheduleDaily(TimeSpan when, Action what)
{
var now = DateTime.Now;
var schedule = now.Date.Add(when);
if (schedule < now)
{
schedule = schedule.AddDays(1.0);
}
return
Observable
.Timer(schedule, TimeSpan.FromDays(1.0))
.Subscribe(_ => what());
}
要打电话就行:
IDisposable runSample = ScheduleDaily(TimeSpan.FromHours(4.0),
() => Process.Start("sample.exe"));
IDisposable deleteFolders = ScheduleDaily(TimeSpan.FromHours(1.0),
() => Directory.Delete(folder_path, recursive: true));
ScheduleDaily
会返回一个方便的IDisposable
,您可以.Dispose()
停止计时器。
无需线程或休眠。非常简单。
答案 3 :(得分:1)
Thread.Sleep()
导致当前线程进入休眠状态,因此线程不会再做任何事情,直到它完成睡眠(除非你打断它或其他东西)。
所以,如果你这样做,你只需要更多的线程。
var scheduleLoopAction = new Action<int, int, string>((int hour, int minute, string processName) =>
{
while (true)
{
var now = DateTime.Now;
var schedule = new DateTime(now.Year, now.Month, now.Day, hour, minute, 00);
if (schedule < now) schedule = schedule.AddDays(1);
System.Threading.Thread.Sleep(schedule.Subtract(now));
System.Diagnostics.Process.Start(processName);
}
});
((new System.Threading.Thread(() => { scheduleLoopAction(4, 0, "sample.exe"); }))).Start();
((new System.Threading.Thread(() => { scheduleLoopAction(1, 0, "sample2.exe"); }))).Start();
这可能不是实现目标的最佳方式,但我认为你想要的东西就像问题中的内容一样。
请注意,线程调用不会阻止,因此此方法将立即完成(与问题中的示例不同,它将永远存在)。如果您希望它阻止,您可以在当前线程中运行最后一个计划,例如
((new System.Threading.Thread(() => { scheduleLoopAction(4, 0, "sample.exe"); }))).Start();
scheduleLoopAction(1, 0, "sample2.exe"); // Runs in current thread