如何在 C# 中每天激活一次线程
Posted
技术标签:
【中文标题】如何在 C# 中每天激活一次线程【英文标题】:How to have a thread activate once a day in C# 【发布时间】:2020-10-12 17:17:18 【问题描述】:我有一个 WPF 应用程序,它的任务是导致旧订单过期。导致订单过期的线程需要每天运行一次。我目前有下面的代码来完成我想要完成的工作(对代码进行了一些简化)。
我的问题是我的方法是否有意义,或者是否有更好的方法来完成任务。
有没有办法让线程等到天变了?这会是一个好的解决方案吗?
我使用的线程类型是否最适合这项工作?
using System.Threading;
public class DailyTask
public static void StartJob()
while (true)
string lastRunFile = "lastRun.txt";
// get the last time the file was written to
DateTime lastRunTime = new System.IO.FileInfo(lastRunFile).LastWriteTime;
// get time span since last run
TimeSpan sinceLastRunTime = DateTime.Today - lastRunTime.Date;
// if a day has passed
if (sinceLastRunTime.Days >= 1)
// write anything to the file to update the lastWriteTime
System.IO.File.WriteAllText(lastRunFile, DateTime.Now.ToString());
// Do the job
DoStuff();
else
// Sleep for an hour
Thread.Sleep(1000 * 60 * 60);
private static void DoStuff()
// Do the daily task
我通过以下方式启动线程:
Thread thr = new Thread(DailyTask.StartJob);
thr.Start();
【问题讨论】:
有很多作业调度工具/库 当然还有更好的方法,例如使用 Windows 任务计划程序每小时(或当一天是新的,例如凌晨 12 点)安排一个作业,所以你不需要一个 while 循环全部。但我的理念是“如果它有效,它就会有效”。我目前看到你的实现有很多问题,但正如你所说,你已经做了“简化”,所以除非你发布真实的代码,否则没有必要详细说明。 如果您不想使用特殊的调度库,您应该考虑使用类似DispatchTimer
的东西,这将与 WPF 的 UI 友好,甚至是来自 @987654325 的常规 Timer
@命名空间。
@JEL,最好在另一个线程中启动你的程序,所以使用thr.Start()
很好。你也可以使用更现代的Task.Run
。我也会对您的代码进行以下改进。 1) 检查 lastRun.txt 文件是否存在,否则 lastRunTime 可能无效。 2) 如果 lastRun.txt 正在被另一个进程使用,则捕获异常,因此您无法读取/写入它。 3)你的Thread.Sleep只存在于ELSE条件中,也就是说,如果你满足IF条件,你就会“完成任务”,然后立即循环回到WHILE循环,不休眠一个小时。
Thread.Sleep(TimeSpan.FromHours(1));
可能更具可读性
【参考方案1】:
下面的sn-p可以帮到你..
using System.Timers;
const double intervalinMilliseconds = 86400000; // 1 day in milliseconds
Timer Timeinterval = new Timer(intervalinMilliseconds);
Timeinterval.Elapsed += new Dostuff();
Timeinterval.Enabled = true;
public void Dostuff(object sender, ElapsedEventArgs e)
【讨论】:
【参考方案2】:您可以使用System.Threading.Timer
类。 Timer 构造函数有period
参数,它指定调用回调的时间段。请参阅此处的示例MSDN。
您可以调用DoStuff()
方法作为回调。
这是更好的解决方案,因为它避免了线程休眠。
您还可以使用事件等待句柄 (AutoResetEvent)。见here
类似:
var currenTime = DateTime.Now;
var nextDay = currenTime.AddDays(1);
var periodTillEndOfTheDay = nextDay.Date - currenTime;
var timer = new Timer(x => DoStuff(), null, TimeSpan.Zero, periodTillEndOfTheDay);
【讨论】:
即使你必须使用如此丑陋的构造,你也应该在 WPF 应用程序中使用DisplatcherTimer
而不是System.Threading.Timer
。
虽然在问题中提到该应用程序是 WPF 应用程序,但要执行的工作似乎是后台。所以Timer也OK。 System.Timers.Timer 在与用户界面 (UI) 线程不同的线程上运行。为了访问用户界面(UI)线程上的对象,需要将操作发布到用户界面(UI)线程的Dispatcher。以上是关于如何在 C# 中每天激活一次线程的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C# 中修改 Cortana 语音激活命令 (XML)?