Windows 服务与计划任务

发布于 2024-07-10 00:49:02 字数 45 浏览 10 评论 0原文

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

What are the cons and pros of windows services vs scheduled tasks for running a program repeatedly (e.g. every two minutes)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

为你鎻心 2024-07-17 00:49:02

更新:

距离我原来的答案已经过去近四年了,这个答案已经非常过时了。 自从 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 方法。

受保护的覆盖 void OnStart (string args) { 

     // 创建工作线程;   这将调用 WorkerFunction 
     // 当我们启动它时。 
     // 由于我们使用单独的工作线程,所以主服务 
     // 线程会快速返回,告诉Windows服务已经启动 
     ThreadStart st = new ThreadStart(WorkerFunction); 
     工作线程=新线程(st); 

     // 设置标志以指示工作线程处于活动状态 
     服务启动=真; 

     // 启动线程 
     工作线程.Start(); 
  } 
  

代码实例化一个单独的线程并附加我们的工作线程
对它起作用。 然后它启动线程并让 OnStart 事件
完整,这样 Windows 就不会认为该服务已挂起。

单线程方法的工作方法。

/// <摘要> 
  /// 该函数将完成所有工作 
  /// 一旦完成任务,它将暂停一段时间; 
  /// 它将继续重复此操作,直到服务停止 
  ///  
  私有无效 WorkerFunction() { 

     // 开始无限循环;   仅当“serviceStarted”时循环才会中止 
     // 标志=假 
     while (服务启动) { 

        // 做一点事 
        // 为了简单起见,这里省略了异常处理 
        EventLog.WriteEntry("服务正在运行", 
           系统.诊断.EventLogEntryType.信息); 

        // 屈服 
        如果(服务已启动){ 
           Thread.Sleep(new TimeSpan(0, 间隔, 0)); 
        } 
     } 

     // 结束线程的时间 
     Thread.CurrentThread.Abort(); 
  } 
  

单线程方法的 OnStop 方法。

受保护的覆盖 void OnStop() { 

     // 告诉工作进程停止的标志 
     服务启动=假; 

     // 给它一点时间来完成任何未完成的工作 
     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 ( Dead Link)

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

Update:

Nearly four years after my original answer and this answer is very out of date. Since TopShelf came along Windows Services development got easy. Now you just need to figure out how to support failover...

Original Answer:

I'm really not a fan of Windows Scheduler. The user's password must be provided as @moodforall points out above, which is fun when someone changes that user's password.

The other major annoyance with Windows Scheduler is that it runs interactively and not as a background process. When 15 MS-DOS windows pop up every 20 minutes during an RDP session, you'll kick yourself that didn't install them as Windows Services instead.

Whatever you choose I certainly recommend you separate out your processing code into a different component from the console app or Windows Service. Then you have the choice, either to call the worker process from a console application and hook it into Windows Scheduler, or use a Windows Service.

You'll find that scheduling a Windows Service isn't fun. A fairly common scenario is that you have a long running process that you want to run periodically. But, if you are processing a queue, then you really don't want two instances of the same worker processing the same queue. So you need to manage the timer, to make sure if your long running process has run longer than the assigned timer interval, it doesn't kick off again until the existing process has finished.

After you have written all of that, you think, why didn't I just use Thread.Sleep? That allows me to let the current thread keep running until it has finished and then the pause interval kicks in, thread goes to sleep and kicks off again after the required time. Neat!

Then you then read all the advice on the internet with lots of experts telling you how it is really bad programming practice:

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

So you'll scratch your head and think to yourself, WTF, Undo Pending Checkouts -> Yes, I'm sure -> Undo all today's work..... damn, damn, damn....

However, I do like this pattern, even if everyone thinks it is crap:

OnStart method for the single-thread approach.

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();
}

The code instantiates a separate thread and attaches our worker
function to it. Then it starts the thread and lets the OnStart event
complete, so that Windows doesn't think the service is hung.

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 method for the single-thread approach.

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));
}

Source: http://tutorials.csharp-online.net/Creating_a_.NET_Windows_Service%E2%80%94Alternative_1%3a_Use_a_Separate_Thread (Dead Link)

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.

亣腦蒛氧 2024-07-17 00:49:02

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

/ru 系统

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

编辑

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

从精美的手册

/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 中,系统 是唯一的选项。

Some misinformation here. Windows Scheduler is perfectly capable of running tasks in the background without windows popping up and with no password required. Run it under the NT AUTHORITY\SYSTEM account. Use this schtasks switch:

/ru SYSTEM

But yes, for accessing network resources, the best practice is a service account with a separate non-expiring password policy.

EDIT

Depending on your OS and the requirements of the task itself, you may be able to use accounts less privileged than Localsystem with the /ru option.

From the fine 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 is available from Vista and Server 2008.

In XP and Server 2003, system is the only option.

夜巴黎 2024-07-17 00:49:02

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

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

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

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

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 only 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 Services, I my mind, are normally used to manage other applications, rather than be a long running application. OR .. they are continuously-running heavyweight applications like SQL Server, BizTalk, RPC Connections, IIS (even though IIS technically offloads work to other processes).

Personally, I favour scheduled tasks over Window Services for repititive maintenance tasks and applications such as file copying/synchronisations, bulk email sending, deletion or archiving of files, data correction (when other workarounds are not available).

For one project I have been involved in the development of 8 or 9 Windows Services, but these sit around in memory, idle, eating 20MB or more memory per instance. Scheduled tasks will do their business, and release the memory immediately.

埋情葬爱 2024-07-17 00:49:02

启动和退出应用程序的开销是多少? 每两分钟一次是很常见的。 与如此频繁地执行应用程序相比,服务可能会让系统运行得更顺畅。

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

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

What's the overhead of starting and quitting the app? Every two minutes is pretty often. A service would probably let the system run more smoothly than executing your application so frequently.

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.

From a user's POV, I wonder which is easier to control. Both services and scheduled tasks are pretty much out of reach for most non-technical users, i.e. they won't even realize they exist and can be configured / stopped / rescheduled and so on.

与酒说心事 2024-07-17 00:49:02

“service”一词与“serv”有一些共同点。 它预计将始终运行并“提供服务”。 任务就是任务。

角色扮演。 如果我是另一个操作系统、应用程序或设备,并且我调用一个服务,我期望它能够运行并且期望得到响应。 如果我(操作系统、应用程序、开发人员)只需要执行一个独立的任务,那么我将执行一个任务,但如果我期望进行通信,可能是双向通信,我需要一个服务。 这与两个事物或想要执行单个任务的单个事物进行通信的最有效方式有关。

然后是日程安排方面。 如果您希望某些内容在特定时间运行,请安排时间。 如果您不知道何时需要它,或者“即时​​”需要它,请提供服务。

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

抛开所有的哲学不谈,当你“快速制作原型”时,就像我的 IT 部门经常做的那样,你会做任何你必须做的事情来维持收支平衡。 一旦原型设计和概念验证的内容完成(通常是在早期规划和发现过程中),您就必须决定什么对长期可持续性更可靠。

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

The word 'serv'ice shares something in common with 'serv'er. It is expected to always be running, and 'serv'e. A task is a task.

Role play. If I'm another operating system, application, or device and I call a service, I expect it to be running and I expect a response. If I (os, app, dev) just need to execute an isolated task, then I will execute a task, but if I expect to communicate, possibly two way communication, I want a service. This has to do with the most effective way for two things to communicate, or a single thing that wants to execute a single task.

Then there's the scheduling aspect. If you want something to run at a specific time, schedule. If you don't know when you're going to need it, or need it "on the fly", service.

My response is more philosophical in nature because this is very similar to how humans interact and work with another. The more we understand the art of communication, and "entities" understand their role, the easier this decision becomes.

All philosophy aside, when you are "rapidly prototyping", as my IT Dept often does, you do whatever you have to in order to make ends meet. Once the prototyping and proof of concept stuff is out of the way, usually in the early planning and discovering, you have to decide what's more reliable for long term sustainability.

OK, so in conclusion, it's highly dependent on a lot of factors, but hopefully this has provided insight instead of confusion.

半岛未凉 2024-07-17 00:49:02

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

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

A Windows service doesn't need to have anyone logged in, and Windows has facilities for stopping, starting, and logging the service results.

A scheduled task doesn't require you to learn how to write a Windows service.

岁月静好 2024-07-17 00:49:02
  1. 使用正确的权限可以更轻松地设置和锁定 Windows 服务。
  2. 服务更加“可见”,这意味着每个人(即:技术人员)都知道去哪里寻找。
  1. It's easier to set up and lock down windows services with the correct permissions.
  2. Services are more "visible" meaning that everyone (ie: techs) knows where to look.
淡淡绿茶香 2024-07-17 00:49:02

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

最近我接到一个要求,每隔 10 分钟捕获一次雷达的屏幕截图(来自气象网站)并保存在服务器中。

这需要我使用网络浏览器。
我通常制作 Windows 服务,所以我决定也制作这一项服务,但它会不断崩溃。
这是我在事件查看器中看到的
故障模块路径:C:\Windows\system32\MSHTML.dll

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

我真的很喜欢马克·兰塞姆接受的答案中推荐的乔恩·加洛韦的文章

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

另外提到的事情,如果使用任务计划程序窗口弹出或控制台窗口弹出。
我从来没有遇到过这样的情况。 它可能会弹出,但至少是瞬时的。

This is an old question but I will like to share what I have faced.

Recently I was given a requirement to capture the screenshot of a radar (from a Meteorological website) and save it in the server every 10 minutes.

This required me to use WebBrowser.
I usually make windows services so I decided to make this one service too but it would keep crashing.
This is what I saw in Event Viewer
Faulting module path: C:\Windows\system32\MSHTML.dll

Since the task was urgent and I had very less time to research and experiment, I decided to use a simple console application and triggered it as a task and it executed smoothly.

I really liked the article by Jon Galloway recommended in accepted answer by Mark Ransom.

Recently passwords on the servers were changed without acknowledging me and all the services failed to execute since they could not logon.
So ppl claiming in the article comments that this is a problem. I think windows services can face same problem (Pls. correct me if I am wrong, I am jus a newbie)

Also the thing mentioned, if using task scheduler windows pop up or the console window pops up.
I have never faced that. It may pop up but it is at least very instantaneous.

愁以何悠 2024-07-17 00:49:02

为什么不两者都提供呢?

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

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

Why not provide both?

In the past I've put the 'core' bits in a library and wrapped a call to Whatever.GoGoGo() in both a service as well as a console app.

With something you're firing off every two minutes the odds are decent it's not doing much (e.g. just a "ping" type function). The wrappers shouldn't have to contain much more than a single method call and some logging.

╰沐子 2024-07-17 00:49:02

一般来说,核心信息是并且应该是代码本身必须可以从每个“触发器/客户端”执行。 因此,从一种方法转向另一种方法不应该是一件复杂的事情。

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

BR,
y

Generally, the core message is and should be that the code itself must be executable from each and every "trigger/client". So it should not be rocket science to switch from one to the other approach.

In the past we used more or less always Windows Services but since also more and more of our customers switch to Azure step by step and the swap from a Console App (deployed as a Scheduled Task) to a WebJob in Azure is much easier than from a Windows Service, we focus on Scheduled Tasks for now. If we run into limitations, we just ramp up the Windows Service project and call the same logic from there (as long as customers are working OnPrem..) :)

BR,
y

扶醉桌前 2024-07-17 00:49:02

Windows 服务需要更多耐心,直到完成。
它的调试和安装有点困难。 真是不要脸了
如果您需要一项必须每秒、每分钟或每小时完成的任务,
你应该选择Windows服务。

计划任务发展很快,有面子。
如果您需要每日或每周任务,可以使用计划任务。

Windows services want more patience until it's done.
It has a bit hard debug and install. It's faceless.
If you need a task which must be done in every second, minute or hour,
you should choice Windows Service.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文