我正在寻找有关实现 Windows 服务的一般性建议。我的要求如下:
- 该服务处理数据库中的行 - 因此,如果某行具有特定状态,它需要做一些工作,写入其他一些表,然后将该行标记为正在处理。
- 服务启动时可能有数千行等待处理 - 它应该处理所有这些行。
- 然后该服务应继续运行,处理写入我的 ForProcessing 表中的所有行。
- 我需要能够优雅地关闭它 - 我不想要任何处理一半的行
- 它需要高效地执行——如果可能的话,我不想轮询数据库
所以我的具体问题是:
- 如何让它保持事件状态并在写入新行时对其做出响应?我可以使用某种类型的
SQLDependency
对象来有效地处理新行吗? - 如何处理正常启动和关闭?
- 从数据库中获取行时,我应该获取所有正在等待处理的行,还是一次只获取一个?
- 假设它已经是后台服务,我会同步处理行吗?换句话说,不需要在后台线程上处理行?
- 我需要考虑哪些帐户及其运行权限?这是部署问题吗?
- 还有其他需要注意的问题或事项吗?
感谢您的任何建议。
附言。除了使用 Windows 服务来实现此目的之外,还有其他合理的替代方法吗?
最佳答案
编写 Windows 服务并没有那么困难,但不可否认,乍一看似乎令人生畏。
就清除业务逻辑而言,我通常会先编写一个命令提示符程序,因为它整体更容易调试。
现在,开始服务。当然,使用 Visual Studio 创建一个 Windows 服务项目。
How do I keep it alive and responding to new rows as they're written? Can I use a SQLDependency object of some kind to efficiently process new rows?
好吧,我不确定你是否可以,但我可以告诉你你需要什么。你将需要一个线程。如果您不在 OnStart 事件中创建新线程,您的服务将立即停止。该线程可以直接使用 .NET 的众多线程机制之一创建,也可以通过某种计时器、FileSystemWatcher(可能不适用于您)或其他方式间接创建。
How do I handle graceful startup and shut down?
您可以在 OnStop 中执行此操作。您可以通过向您的线程发送信号来做到这一点,也许是通过一个全局变量,它是时候关闭了。然后,由您的线程及时通知信号并清理并退出线程。如果您正在处理可能需要超过 20 秒的时间,您需要告诉 SCM(服务控制管理器)您需要更多时间。如果你不这样做,停止服务的用户会收到消息说服务没有响应,最终会被杀死。
When picking up rows from the db, should I fetch all that are awaiting processing, or just one at a time?
这是一个商业决策。可能应该取决于每个处理需要多长时间,以便您可以在发生停止时及时处理。
Presumably, given that it is already a background service, I would process rows synchronously? In otherwords, there is no need to process rows on background threads?
同样,这是一个商业决策,但是是的,我可能会保持同步。
What do I need to think about in terms of accounts and under what permissions it runs? Is this a deployment issue?
好吧,这一切都取决于。 SQL Server 是在同一个盒子上吗?您使用的是 Windows 身份验证吗?如果 SQL 不在同一个框上,您将不得不使用用户帐户或可能是 Network Service
。创建服务项目时,您需要添加安装程序。创建项目后,您会得到一个组件类——在灰色屏幕上,右键单击并选择 Add Installer
。这将创建一个新的组件类,其中已经安装了两个模块。 serviceIntaller1 包含服务名称、显示名称、描述以及启动类型(手动、自动等)等信息。另一个是 serviceProcessInstaller1,您可以在此处决定要使用的登录帐户。
Any other gotchas or things to be aware of?
嗯,大概吧。但是今天早上我还没喝咖啡。
实际上,最重要的事情是规划如何让您的线程保持事件状态并响应最终的 OnStop 请求。例如,如果您要尝试使用 SqlDependency
类,您可能需要在 OnStart 中创建一个 Manual 或 AutoResetEvent,启动您的线程并让您的线程设置 SqlDependency
然后阻止重置事件。然后,在您的 OnStop 中释放您的重置事件,以便您的线程可以清理并离开。之后,就只是滑下山了!
玩得开心!
关于c# - 实现 Windows 服务 - 如何满足这些要求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5677122/