C# 计划任务系列
Posted
技术标签:
【中文标题】C# 计划任务系列【英文标题】:C# Scheduled Series Of Tasks 【发布时间】:2014-05-22 15:19:45 【问题描述】:我正在将 Classic ASP/VBScript 应用程序转换为 C#/ASP.Net。应用程序的 VBScript 部分是每个月在特定日期执行的一系列单独的脚本,每个单独的任务都在 Windows 调度程序中设置。大约有 35 个任务,包括数据库插入(保存每月历史数据、保存汇总账单数据)以及将一系列 Crystal Reports 导出为 PDF 和 Excel。每个任务都安排在一分钟左右,因为我不想同时请求使数据库服务器不堪重负。
当我在 C# 中处理此问题时,我想知道是否有一种方法可以在一个应用程序中完成,而不是我在 VBScript 中采用的单独脚本方法。我对 C# 很满意,因为在过去一年左右的时间里,我一直在使用它将应用程序的网站部分转换为 ASP.Net MVC,但我没有使用 C# 中的定时事件的经验。我正在考虑通过为每个任务创建一个单独的函数来解决这个问题,每个任务之间都有睡眠,以便在继续执行下一个任务之前有足够的时间进行数据库处理。类似于以下内容:
p.DoTask1();
Thread.Sleep(60000);
p.DoTask2();
Thread.Sleep(60000);
p.DoTask3();
Thread.Sleep(60000);
etc ...
这将包含在一个控制台应用程序中,该应用程序本身将在 Windows 调度程序中设置。
这是一种合理的方法吗?有更好的方法吗?我已经阅读了有关计时器和任务的信息,但我不确定它们是否适合我想要完成的任务。
【问题讨论】:
@Amicable 我的应用程序会知道数据库任务已完成,还是只知道它已将任务交给数据库服务器?另外,如果睡眠可以,我真的需要使用任务吗?我假设睡眠是最简单的选择。在我的场景中使用更复杂的选择是否有任何令人信服的理由? @Amicable 大多数 db 任务都很快完成,所以每个任务之间的一分钟给了他们很多时间,所以这部分并不重要,但是我喜欢你知道什么时候 db 任务的方法由返回的记录完成,然后继续下一个任务 @Amicable 您能否在答案中总结您的 cmets,我会接受吗?谢谢。 好的,我已经做到了。很高兴我能帮忙:) @LouiseEggleton,在 ASP.NET 中你真的应该使用async/await
来处理任务,像这样:***.com/a/22962699/1768303
【参考方案1】:
只是另一个建议运行它的价值。您可以查看Quartz.Net 而不是在 Windows 下运行控制台应用程序,这样您就可以通过您的网站运行任务(或 Quartz 中的作业)并一次部署和更新所有代码,而不需要单独的控制台应用程序.您可以使用 CRON 时间设置来安排它们 - 尽管站点需要运行,因此如果在奇怪的时间运行,您可能需要监控或 ping 设置。
然后,您可以使用单独的计划设置您的任务,或者像上面其他人建议的那样,设置一个任务,其中的步骤在其他任务完成时运行。
【讨论】:
@user351952 我喜欢有一个单独的应用程序,这样网站就不会杂乱无章,而且还有性能,正如你提到的,从网站运行调度程序的可靠性问题。无论如何,我查看了 Quartz.net,它可以从控制台应用程序中使用,所以我正在考虑 Quartz.net 和 .Net 的 Task 类。如果 Quartz.net 比 .Nets 任务系统有显着优势,我会选择 Quartz.net【参考方案2】:您可以在前一个任务完成后使用Task.ContinueWith 触发每个任务。详情请参阅this related answer。
数据库查询返回受影响的行,这就是您告诉数据库已完成您执行的查询的运行方式,而不是仅仅将其传递给数据库。
我看到使用这样的方法比简单地休眠线程的优点是您永远不会同时运行多个任务,并且任务之间不会有停机时间。
这有多重要取决于您对情况有更深入的了解。
【讨论】:
【参考方案3】:Windows 调度程序启动的控制台应用程序对我来说很好。我自己为每天运行一次的数据库集成程序执行此操作。 对于定时事件,我使用 System.Threading.Timer 类,如下所示:
//here you set a time to start
var timeToStart = 60000;
//here an interval, if it's not recurring use Timeout.Infinite
var tRefresh = Timeout.Infinite;
//here the method, I make it static
TimerCallback tcb1 = ClassName.MethodName;
var timer = new System.Threading.Timer(tcb1, null, timeToStart, tRefresh);
您可以创建多个计时器,并为它们分配不同的任务,以不同的开始时间来解决您的问题。
【讨论】:
以上是关于C# 计划任务系列的主要内容,如果未能解决你的问题,请参考以下文章