如何只有一个程序实例运行计划任务?

时间:2012-07-25 08:16:36

标签: c# multithreading scheduled-tasks

我的软件针对单个数据库在多台计算机上运行。

我希望每天在软件中执行任务 - 例如。中午。

我如何确保此任务:

  • 每天只执行一次,
  • 执行无论当天哪台机器/用户正在运行该软件,
  • 不与软件的任何其他实例同时执行?

2 个答案:

答案 0 :(得分:2)

在客户端中执行此操作的问题在于,您的用户可能一天都不会运行该软件,或者他们可能在操作期间遭受硬件故障(例如断电),从而导致永久锁定行。您无法保证任务的完整性,甚至无法保证任务能够运行。

如果您需要确保它运行而不管用户每天实际使用您的软件,这都适用于数据库服务器上的计划任务(可用于WindowsLinux / UNIX

创建执行任务的可执行文件,然后创建计划任务以每天运行它。这样,只要数据库机器启动,您就有一个始终运行的实例,并且您不必担心跨客户端跟踪作业执行。


好的,所以您现在说由于公司规则,您无法在数据库框上运行计划任务。这是我使用的方案:

  1. 为作业调度创建一个表。为每个作业提供运行的日期/时间,作业开始的时间(如果未启动,则为null),进度字段,以及任务所需的名称和其他信息。
  2. 每隔5分钟左右进行一次客户端轮询,运行查询以查找过去有日期的作业。选择其行未锁定的第一个作业。
  3. 锁定行并将“time job started”字段更新为当前时间。
  4. 执行任务,在作业的一部分完成时更新进度字段。
  5. 成功时删除行,否则将该行标记为“失败”。
  6. 重要的部分是“时间工作开始”字段,它允许客户检查作业是否在很久以前(例如3小时)启动但从未完成,因此可以重试或用户提醒,具体取决于进步值。

答案 1 :(得分:1)

您可以在数据库中使用包含单行的表。使用事务来锁定包含上次更新日期的行。

每隔X分钟:

  • 如果记录被锁定,则表示某人正在执行该作业。什么都不做。
  • 如果记录已过期并解锁,请将其锁定并完成工作。如果失败,请解锁记录。如果成功,请使用当前日期更新记录。
  • 如果记录包含当前日期,则不执行任何操作。

使用SQL Server的示例

如果您在事务中运行它,它将锁定来自其他客户端的行

UPDATE Test WITH (ROWLOCK)
SET UpdateDate = yourDate
WHERE PrimaryKey = yourkey