在重复运行程序(例如,每两分钟一次)方面,使用Windows服务和计划任务的优缺点是什么?
在重复运行程序(例如,每两分钟一次)方面,使用Windows服务和计划任务的优缺点是什么?
更新:
距我原来的答案已经近四年了,这个答案已经非常过时了。由于 TopShelf 的出现,Windows 服务的开发变得很容易。现在你只需要想办法支持故障转移就可以了...
原来的答案:
我真的不是 Windows 计划任务的粉丝。正如@moodforall 在上面指出的,必须提供用户密码,当有人更改该用户的密码时会很棘手。
Windows 计划任务的另一个主要问题是它以交互方式运行而不是作为后台进程运行。当每20分钟弹出15个 MS-DOS 窗口时,在 RDP 会话中,您会因为没有安装它们作为 Windows 服务而自责。
无论您选择什么,我都建议您将处理代码从控制台应用或 Windows 服务中分离出来。然后您可以选择,要么从控制台应用程序调用工作进程并将其连接到 Windows 计划任务,要么使用 Windows 服务。
您会发现计划 Windows 服务不是一件有趣的事情。一个相当常见的场景是您有一个长时间运行的过程,您想要定期运行该过程。但是,如果您正在处理队列,则实际上不希望两个相同的工作进程处理相同的队列。因此,您需要管理计时器,以确保如果您的长时间运行的过程运行时间超过分配的计时器间隔,则在现有进程完成之前不会再次启动。
在您编写了所有这些之后,您会想,为什么我不使用 Thread.Sleep 呢?它允许当前线程继续运行,直到它完成,然后暂停间隔开始,线程进入睡眠状态,并在所需时间后再次启动。很棒!
然后您会阅读互联网上的所有建议,很多专家告诉您这真是糟糕的编程实践:
所以您会挠头并想:“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(); }
这段代码实例化了一个单独的线程,并将我们的工作函数附加到它上面。然后启动线程并让 OnStart 事件完成,这样 Windows 就不会认为服务已挂起。
单线程方法的工作方法。
/// <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)); }
我多年来一直使用这种方式运行许多 Windows 服务,它对我很有效。我仍然没有看到人们认可的推荐模式。只要做适合自己的就可以了。
但是,为了访问网络资源,最好使用一个具有单独的不过期密码策略的服务帐户。编辑根据您的操作系统和任务本身的要求,您可能可以使用低于Localsystem特权的帐户和/ru SYSTEM
/ru
选项。根据手册的细节。/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.
任务计划程序 2.0 可在 Vista 和 Server 2008 中使用。
在 XP 和 Server 2003 中,system
是唯一的选项。
LocalService
和 NetworkService
在 schtasks
v2 Vista 及以后版本中可用,并且应尽可能使用。当时,这是指 XP 和 Server 2003 中的 schtasks
,其仅根据旧版本手册 http://technet.microsoft.com/en-us/library/bb490996.aspx 接受 System
作为参数。 - Amit Naidu在.NET开发中,我通常从开发控制台应用程序开始,所有日志输出都将运行到控制台窗口。但是,只有在使用命令参数/console
运行时,它才是一个纯粹的控制台应用程序。当没有这个参数时,它就像一个Windows服务,会在我自己编写的定时器上保持运行。
在我的看法中,Windows服务通常用于管理其他应用程序,而不是作为长时间运行的应用程序。或者,它们是像SQL Server、BizTalk、RPC连接、IIS这样的持续运行的重量级应用程序(尽管IIS技术上会将工作分配给其他进程)。
就我个人而言,针对重复性的维护任务和应用程序,例如文件复制/同步、批量邮件发送、文件删除或存档、数据校正(当没有其他解决方法时),我更喜欢使用定时任务而不是Windows服务。
在一个项目中,我参与开发了8或9个Windows服务,但是它们会闲置在内存中,每个实例会占用20MB或更多的内存。定时任务会完成它们的业务,并立即释放内存。
启动和退出应用程序的开销有多大?每两分钟运行一次相当频繁。使用服务可能会比如此频繁地执行您的应用程序更加顺畅地让系统运行。
这两种解决方案都可以在用户未登录时运行程序,因此没有区别。但编写服务比普通桌面应用程序更为复杂 - 您可能需要一个单独的GUI客户端,通过TCP/IP、命名管道等与服务应用程序通信。
从用户的角度来看,我想知道哪个更容易控制。对于大多数非技术用户来说,服务和计划任务几乎是无法触及的,即他们甚至不会意识到它们的存在,并且可以进行配置/停止/重新安排等操作。
Windows服务不需要任何人登录,Windows提供了停止、启动和记录服务结果的功能。
计划任务不需要您学习如何编写Windows服务。
NT AUTHORITY\LocalService
或 NT AUTHORITY\NetworkService
),否则任何提供的密码都将被忽略,因为这些帐户没有密码。 - Ian Boyd这是一个久远的问题,但我想分享一下我所面临的情况。
最近,我收到了一个需求,需要每隔10分钟从气象网站捕获雷达截图并保存在服务器中。
这要求我使用WebBrowser。 通常我会制作Windows服务,所以我决定把这个服务也做成服务,但它不断崩溃。 以下是我在事件查看器中看到的内容: 故障模块路径:C:\Windows\system32\MSHTML.dll
由于任务非常紧急,我没有多少时间进行研究和实验,所以我决定使用一个简单的控制台应用程序,并将其作为任务触发,顺利地执行了它。
我真的很喜欢Jon Galloway的文章,这是被Mark Ransom接受的答案推荐的。
最近,服务器上的密码在没有通知我的情况下更改了,所有的服务都无法执行,因为它们无法登录。 因此,在文章评论中声称这是一个问题的人。我认为Windows服务可能会面临相同的问题(如果我错了,请纠正我,我只是一个新手)
另外,提到的东西,如果使用任务计划程序,Windows弹出或控制台窗口弹出。 我从未遇到过这种情况。它可能会弹出,但至少非常瞬间。
为什么不两者兼备呢?
过去我曾将“核心”部分放在库中,并在服务和控制台应用程序中包装调用Whatever.GoGoGo()。
如果每两分钟就要启动一次某些东西,很可能它并没有做太多事情(例如仅仅是一个“ping”类型的函数)。包装器不应该包含太多内容,只需一个方法调用和一些日志记录即可。
NT AUTHORITY\NetworkService
是一个具有有限权限的账户。 - Ian Boyd