窗口服务与预定任务

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

98025 次浏览

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

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

启动和退出应用程序的开销是多少?每两分钟一次。服务可能会让系统比频繁地执行应用程序运行得更平稳。

Both solutions can run the program when user isn't logged in, so no difference there. Writing a service is somewhat more involved than a regular desktop app, though - you may need a separate GUI client that will communicate with the service app via TCP/IP, named pipes, etc.

从用户的视角来看,我想知道哪个更容易控制。对于大多数非技术用户来说,服务和计划任务都非常遥不可及,也就是说,他们甚至不会意识到它们的存在,可以配置/停止/重新调度等等。

  1. 使用正确的权限设置和锁定 Windows 服务更加容易。
  2. 服务更加“可见”,这意味着每个人(例如: 技术人员)都知道去哪里寻找。

为什么不两者都提供呢?

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

对于你每两分钟发射一次的东西,它没有做太多的事情(例如只是一个“ ping”类型的函数)。包装器不应该只包含一个方法调用和一些日志记录。

更新:

在我最初的答案出现将近四年之后,这个答案已经非常过时了。自从 TopShelf出现以来,Windows 服务的开发变得容易了。现在您只需要找出如何支持故障转移..。

原答案:

我真的不喜欢 Windows 调度程序。用户的密码必须提供 @ moodforall指出以上,这是有趣的,当有人改变该用户的密码。

Windows 调度程序的另一个主要烦恼是它是交互式运行的,而不是作为后台进程。在 RDP 会话期间,每隔20分钟就会弹出15个 MS-DOS 窗口,如果你没有把它们作为 Windows 服务安装的话,你会后悔的。

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

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

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

然后,你在互联网上阅读了所有的建议,许多专家告诉你这种编程实践是多么糟糕:

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

因此,你会挠挠头,心想,卧槽,撤销未决退房-> 是的,我确信-> 撤销所有今天的工作... ..。该死,该死,该死。

然而,我确实喜欢这种模式,即使所有人都认为它是垃圾:

单线程方法的 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 method for the single-thread approach.

/// <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 (死亡链接)

I've been running lots of Windows Services like this for years and it works for me. I still haven't seen a recommended pattern that people agree on. Just do what works for you.

这里有些错误信息。Windows 计划程序完全能够在后台运行任务,而不会弹出窗口,也不需要密码。在 NT 授权系统帐户下运行它。使用这个 schasks 开关:

/ru 系统

但是,对于访问网络资源,最佳实践是使用单独的不过期密码策略的服务帐户。

剪辑

根据您的操作系统和任务本身的要求,您可以通过 /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.

任务计划程序2.0 可从 Vista 和 Server 2008获得。

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

In .NET development, I normally start off by developing a Console Application, which will run will all logging output to the console window. However, this is 只有 a Console Application when it is run with the command argument /console. When it is run without this parameter, it acts as a Windows Service, which will stay running on my own custom coded scheduled timer.

在我看来,Windows 服务通常用于管理其他应用程序,而不是长时间运行的应用程序。或者。.它们是连续运行的重量级应用程序,如 SQL Server、 BizTalk、 RPC Connections、 IIS (即使 IIS 在技术上将工作卸载到其他进程)。

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

对于一个项目,我参与了8或9 Windows 服务的开发,但是这些服务都处于内存空闲状态,每个实例占用20MB 或更多的内存。预定的任务将执行它们的业务,并立即释放内存。

“服务”这个词与“服务者”有一些共同之处。它应该一直在运行,并服务于。任务就是任务。

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

然后是日程安排方面的问题。如果您希望在特定时间运行某些内容,请安排时间表。如果你不知道你什么时候需要它,或者需要它“在飞行中”,服务。

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

抛开所有哲学不谈,当你像我的 IT 部门经常做的那样“快速原型化”时,你会为了达到收支平衡而不惜一切代价。一旦原型设计和概念验证工作已经完成,通常是在早期的规划和发现阶段,你必须决定什么对于长期可持续性来说是更可靠的。

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

这是一个古老的问题,但我愿意分享我所面临的问题。

最近,我被要求捕捉一个雷达的屏幕截图(从气象网站) ,并保存在服务器每10分钟。

这就要求我使用 WebBrowser。 我通常使窗口服务,所以我决定使这一个服务太,但它会继续崩溃。 这就是我在事件查看器中看到的 错误模块路径: C: Windows system 32 MSHTML.dll

由于任务紧迫,我没有太多时间去研究和实验,我决定使用一个简单的控制台应用,把它作为一个任务来执行,并且执行得很顺利。

我真的很喜欢 作者: Jon Galloway推荐的接受的答案由马克兰塞姆。

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

还提到的事情,如果使用任务调度程序窗口弹出或控制台窗口弹出。 我从来没有面对过这种情况,它可能会突然出现,但至少是瞬间发生的。

Windows 服务在完成之前需要更多的耐心。 它有点难调试和安装。它的脸。 如果你需要一项必须在每一秒、每一分钟或每一小时内完成的任务, 你应该选择视窗服务。

Scheduled Task is quickly developed and has a face. If you need a daily or weekly task, you can use Scheduled Task.

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

在过去,我们或多或少总是使用 Windows 服务,但由于越来越多的客户一步一步地转向 Azure,而且从控制台应用程序(作为计划任务部署)到 Azure 中的 WebJob 的转换要比从 Windows 服务部署容易得多,所以我们现在关注计划任务。如果我们遇到限制,我们只需增加 Windows 服务项目并从那里调用相同的逻辑(只要客户使用 OnPrem)。.):)

y