Windows服务与计划任务

问题描述 投票:105回答:11

重复运行程序(例如,每两分钟),Windows服务与计划任务的缺点和优点是什么?

windows-services scheduled-tasks
11个回答
47
投票

更新:

在我的原始答案将近四年之后,这个答案已经过时了。自从TopShelf出现以来,Windows服务开发变得轻而易举。现在您只需要弄清楚如何支持故障转移......

原答案:

我真的不是Windows Scheduler的粉丝。用户的密码必须以@moodforall指出的方式提供,当有人更改用户的密码时,这很有趣。

Windows Scheduler的另一个主要烦恼是它以交互方式运行而不是作为后台进程运行。当在RDP会话期间每20分钟弹出15个MS-DOS窗口时,你会踢自己并没有将它们安装为Windows服务。

无论您选择什么,我当然建议您将处理代码分离到控制台应用程序或Windows服务的不同组件中。然后您可以选择从控制台应用程序调用工作进程并将其挂接到Windows Scheduler,或使用Windows服务。

您会发现安排Windows服务并不好玩。一个相当常见的情况是您需要定期运行一个长时间运行的进程。但是,如果您正在处理队列,那么您实际上不希望同一个工作组的两个实例处理相同的队列。因此,您需要管理计时器,以确保长时间运行的进程运行的时间超过指定的计时器间隔,在现有进程完成之前,它不会再次启动。

在你写完所有这些之后,你想,为什么我不使用Thread.Sleep?这允许我让当前线程继续运行直到它完成然后暂停间隔开始,线程进入睡眠状态并在所需时间后再次启动。整齐!

然后你会阅读互联网上的所有建议,很多专家告诉你如何编程实践真的很糟糕:

http://msmvps.com/blogs/peterritchie/archive/2007/04/26/thread-sleep-is-a-sign-of-a-poorly-designed-program.aspx

所以你会抓住你的头,想想自己,WTF,撤消未决的结账 - >是的,我敢肯定 - >撤销所有今天的工作......该死的,该死的,该死的....

但是,我喜欢这种模式,即使每个人都认为它是垃圾:

用于单线程方法的OnStart方法。

protected override void OnStart (string args) {

   // Create worker thread; this will invoke the WorkerFunction
   // when we start it.
   // Since we use a separate worker thread, the main service
   // thread will return quickly, telling Windows that service has started
   ThreadStart st = new ThreadStart(WorkerFunction);
   workerThread = new Thread(st);

   // set flag to indicate worker thread is active
   serviceStarted = true;

   // start the thread
   workerThread.Start();
}

代码实例化一个单独的线程并将我们的worker函数附加到它。然后它启动线程并让OnStart事件完成,以便Windows不认为服务挂起。

单线程方法的Worker方法。

/// <summary>
/// This function will do all the work
/// Once it is done with its tasks, it will be suspended for some time;
/// it will continue to repeat this until the service is stopped
/// </summary>
private void WorkerFunction() {

   // start an endless loop; loop will abort only when "serviceStarted"
   // flag = false
   while (serviceStarted) {

      // do something
      // exception handling omitted here for simplicity
      EventLog.WriteEntry("Service working",
         System.Diagnostics.EventLogEntryType.Information);

      // yield
      if (serviceStarted) {
         Thread.Sleep(new TimeSpan(0, interval, 0));
      }
   }

   // time to end the thread
   Thread.CurrentThread.Abort();
}

用于单线程方法的OnStop方法。

protected override void OnStop() {

   // flag to tell the worker process to stop
   serviceStarted = false;

   // give it a little time to finish any pending work
   workerThread.Join(new TimeSpan(0,2,0));
}

来源:http://tutorials.csharp-online.net/Creating_a_.NET_Windows_Service%E2%80%94Alternative_1%3a_Use_a_Separate_Thread(死链接)

多年来我一直在运行这样的Windows服务,它对我有用。我还没有看到人们同意的推荐模式。做对你有用的事情。


0
投票

Windows服务需要更多的耐心才能完成。它有点难以调试和安装。这是不露面的。如果您需要每隔一分钟,每分钟或每小时完成一项任务,则应选择Windows服务。

计划任务很快就会发展出来并且有一张脸。如果您需要每日或每周任务,则可以使用“计划任务”。


0
投票

通常,核心消息是并且应该是代码本身必须可以从每个“触发器/客户端”执行。因此,从一种方法切换到另一种方法不应该是火箭科学。

在过去,我们或多或少总是使用Windows服务,但也因为越来越多的客户逐步切换到Azure,从控制台应用程序(部署为计划任务)到Azure中的WebJob的交换比从在Windows服务中,我们现在专注于计划任务。如果我们遇到限制,我们只是提升Windows服务项目并从那里调用相同的逻辑(只要客户正在使用OnPrem ..):)

BR,y


16
投票

这里有一些错误信息。 Windows Scheduler完全能够在后台运行任务,而不会弹出窗口,也不需要密码。在NT AUTHORITY \ SYSTEM帐户下运行它。使用这个schtasks开关:

/ RU SYSTE M.

但是,是的,为了访问网络资源,最佳做法是使用单独的非过期密码策略的服务帐户。

编辑

根据您的操作系统和任务本身的要求,您可以使用/ru选项使用权限低于Localsystem的帐户。

从精美的manual

/RU username

A value that specifies the user context under which the task runs. 
For the system account, valid values are "", "NT AUTHORITY\SYSTEM", or "SYSTEM". 
For Task Scheduler 2.0 tasks, "NT AUTHORITY\LOCALSERVICE", and 
"NT AUTHORITY\NETWORKSERVICE" are also valid values.

Task Scheduler 2.0可从Vista和Server 2008获得。

在XP和Server 2003中,system是唯一的选择。


11
投票

启动和退出应用程序的开销是多少?每两分钟就经常发生一次。服务可能会让系统比如此频繁地执行应用程序更顺畅。

当用户没有登录时,两种解决方案都可以运行程序,因此没有区别。但是,编写服务比常规桌面应用程序更复杂 - 您可能需要一个单独的GUI客户端,它将通过TCP / IP,命名管道等与服务应用程序通信。

从用户的POV,我想知道哪个更容易控制。对于大多数非技术用户来说,服务和计划任务都是遥不可及的,即他们甚至不会意识到它们存在并且可以被配置/停止/重新安排等等。


10
投票

在.NET开发中,我通常从开发一个控制台应用程序开始,该应用程序将运行所有日志记录输出到控制台窗口。但是,当使用命令参数/console运行时,这只是一个控制台应用程序。当它在没有此参数的情况下运行时,它将充当Windows服务,它将继续在我自己的自定义编码计划计时器上运行。

我认为Windows服务通常用于管理其他应用程序,而不是长期运行的应用程序。或者..他们不断运行重量级应用程序,如SQL Server,BizTalk,RPC Connections,IIS(即使IIS技术上卸载工作到其他进程)。

就个人而言,我更喜欢Window Services上的计划任务,用于重复维护任务和应用程序,例如文件复制/同步,批量电子邮件发送,文件删除或存档,数据更正(当其他解决方法不可用时)。

对于一个项目,我参与了8或9个Windows服务的开发,但这些项目在内存中闲置,每个实例占用20MB或更多内存。计划任务将完成他们的业务,并立即释放内存。


8
投票

'serv'ice这个词与'serv'er有共同之处。预计它将一直运行,并且'serv'e。任务是一项任务。

角色扮演。如果我是另一个操作系统,应用程序或设备而我称之为服务,我希望它能够运行,我希望得到响应。如果我(os,app,dev)只需要执行一个孤立的任务,那么我将执行一个任务,但如果我希望进行通信,可能是双向通信,我想要一个服务。这与两个事物进行通信的最有效方式有关,或者与想要执行单个任务的单个事物有关。

那就是调度方面。如果您想在特定时间运行某些东西,请安排。如果您不知道何时需要它,或者需要“即时”服务。

我的回答在本质上更具哲学性,因为这与人类如何与另一个人互动和合作非常相似。我们越了解沟通的艺术,“实体”理解他们的角色,这个决定就变得越容易。

抛开所有的哲学,当你“快速原型化”时,正如我的IT部门经常做的那样,你做任何你必须做的事情来维持生计。一旦原型设计和概念验证不在考虑之中,通常在早期规划和发现中,您必须决定哪些方案对于长期可持续性更可靠。

好吧,总而言之,它高度依赖于很多因素,但希望这提供了洞察力而不是混乱。


4
投票

Windows服务不需要任何人登录,Windows具有停止,启动和记录服务结果的工具。

计划任务不需要您学习如何编写Windows服务。


4
投票
  1. 使用正确的权限设置和锁定Windows服务更容易。
  2. 服务更“可见”意味着每个人(即:技术人员)都知道在哪里看。

2
投票

为什么不同时提供?

在过去,我将“核心”位放在一个库中,并在服务和控制台应用程序中包含对Whatever.GoGoGo()的调用。

对于你每两分钟开除一次的东西,赔率是不错的,它没有做太多(例如只是一个“ping”类型的功能)。包装器不应包含多于一个方法调用和一些日志记录。


2
投票

这是一个老问题,但我想分享我所面对的问题。

最近我被要求捕获雷达的截图(来自气象网站)并且每10分钟将其保存在服务器中。

这要求我使用WebBrowser。我经常制作Windows服务,所以我决定也提供这个服务,但它会继续崩溃。这是我在事件查看器错误模块路径中看到的:C:\ Windows \ system32 \ MSHTML.dll

由于任务紧急,我没有多少时间进行研究和实验,我决定使用一个简单的控制台应用程序并将其作为一项任务触发,并顺利执行。

我真的很喜欢Mark Ransom接受的答案中推荐的article by Jon Galloway

最近服务器上的密码被更改而没有确认我,并且所有服务都无法执行,因为他们无法登录。所以ppl在文章中声称这是一个问题。我认为Windows服务可能面临同样的问题(如果我错了,请纠正我,我是个新手)

还有提到的事情,如果弹出任务调度程序窗口或弹出控制台窗口。我从未面对过那个。它可能会弹出,但它至少是非常瞬间的。

© www.soinside.com 2019 - 2024. All rights reserved.