C#windows服务+长时间运行的工作流程

时间:2010-08-10 13:16:12

标签: c# windows-services

我正在开始开发一个Windows服务,并希望在进行深入介绍之前先咨询stackoverflow的脑力劳动,以了解处理它的最佳方法。

这将是我的第一个Windows服务,我对线程并不熟悉,这就是我假设的建议(但我很想学习!)。

该服务将具有以下高级别功能:

  • 监视新文件的文件夹(计划使用FileSystemWatcher)。
  • 检测到文件后,它会排队等待上传到外部主机。
  • 如果队列中有文件,则将这些文件串行HTTP POST到外部主机。
    • 文件必须一次一个地POST(连续),并且必须使用HTTP POST进行传输。
  • 成功进行HTTP POST后,它将删除本地文件,并在必要时移至上传队列中的下一个文件并重复此过程。

即使在这个高级别,我可以预见的问题是,文件到外部主机的HTTP POST可能需要很长时间。

有哪些设计选项可以最好地处理Windows服务的长期运行方面?我是否应该根据使用Windows服务作为此解决方案的实现?我应该调查一个独立的应用程序吗?

提前感谢溢出!

7 个答案:

答案 0 :(得分:3)

Windows服务IMO并不是一个坏主意,特别是因为您希望它不断尝试检测文件夹中的文件。 HTTP POST限制很重要,但您知道它将占用的时间和资源。我认为你最关心的是排队和资源管理。您需要将每个传输转换为BackgroundWorker进程,以便可以独立完成多个文件,但您还需要一个可以限制可以旋转的BackgroundWorker对象数量的管理类。否则你会遇到内存管理问题,网络堵塞,谁知道还有什么。

您应该关注文件夹中出现的文件的最差/最佳情况。同时出现的最大文件数是多少,文件的最大大小是什么,当文件夹开始“备份”时会发生什么,因为HTTP POST没有足够快地将它们传送到目的地。目标主机无法访问时会发生什么?当系统重新启动“中间交付”时会发生什么?是否有确定文件传递优先级的来源?是否存在文件传递必须中断或交易逆转的情况?

我认为Windows服务是正确的选择,与FileSystemWatcher结合使用。请注意您的资源使用情况。

答案 1 :(得分:1)

Windows服务绝对是您的选择。在启动服务的方法中,您必须创建必要的FileSystemWatcher实例。

创建新文件时,将触发事件,您必须及时处理这些事件。事件在线程池的线程上执行,如果事件处理程序没有立即返回,则未来的事件可能会丢失。这意味着您必须排队某种形式的任务。您可以使用.NET 4中的新版Task Parallel LibraryBackgroundWorker classThreadPool.QueueUserWorkItem method或类似内容。通常,这些技术都使用大小有限的.NET线程池来限制服务将使用的系统资源量。

每次创建新文件时对新任务进行排队将允许任务并行执行。如果您只希望一次执行单个任务,则必须将任务放入队列中。您可以使用易失性内存中队列,但另一种方法是使用持久和事务性MSMQ队列。如果文件足够小以存储在队列中,则可以以事务方式读取,排队和删除文件。然后,另一个任务必须将队列中的文件出列并处理它们。任何失败都会回滚事务并将文件保留在队列中。这将解决尝试将文件系统用作事务数据库的问题。

如果您的文件快速到达,则必须处理错过FileSystemWatcher的事件的情况。定期(即每分钟一次)服务扫描文件系统的方法可能会更好地为您服务。这可以使用计时器类(System.Timers.Timer classSystem.Threading.Timer class)来完成。

在启动期间,您的服务必须枚举现有但未经处理的文件并将其排队等待处理。

如果您的服务必须非常可靠,您必须考虑所有可能的故障情况,例如意外终止服务或磁盘已满。

答案 2 :(得分:0)

好吧,如果我理解你的话,你想要达到的目标并不复杂。

我会选择Windows服务和FileSystemWatcher。

您需要做的线程不多。我唯一要解决的是文件上传,这可以通过BackgroundWorker轻松完成。通过线程化,您可以异步上传多个文件。

如果您需要更多帮助,请与我们联系。

答案 3 :(得分:0)

我最近使用SmartThreadPool来管理Windows服务应用程序中的并发FTP上传。

Windows服务使用Quartz.Net计划来启动FTP上传作业,但我需要在很短的时间内完成200次上传。每个单独上传需要15分钟,但所有200个需要在2小时内完成。

当Quartz触发其预定事件时,我在SmartThreadPool中填充了代表每个FTP端点的200个类实例,让SmartThreadPool管理资源使用情况。 (当我们的任务由Quartz运行需要很长时间,很长一分钟或更长时间时,我们遇到了Quartz触发器丢失的问题)

我发现我很容易扩展到60个线程(我去过的最高线程),几乎是线性并发。也就是说,连续200次上传几乎需要50个小时才能完成,让SmartThreadPool最多使用50个线程将整个过程缩短到接近1个小时。

这种方法对我们来说效果非常好,我会推荐它。

答案 4 :(得分:0)

Windows服务是可行的方法。

我没有预见到任何问题,因为我之前几乎完全相同,除了我连接到数据库而不是http服务,并且没有任何问题。

您不需要多线程,特别是因为您一次只发布一个文件。

如果您有一个应用程序来监控您的服务,并在发生故障时发送电子邮件/短信,那将非常有用。

答案 5 :(得分:0)

FileSystemWatcher的

此系统的一个大问题是,当文件系统最初在目录中创建一个条目时,事件通常会开始触发,并且事件将在写入文件时继续触发。但是,一般的期望是文件系统观察程序将在文件完全写入目录后触发。即使filesystemwatcher已经开始触发事件,这也会导致尚未完成传输到目录的大文件出现问题。

一个强大的解决方案必须使用某种类型的测试来包装filesystemwatcher事件,该文件已完成写入。我目前没有任何方便的参考资料,但有很多解决方案可以解决这个问题。

答案 6 :(得分:0)

我同意其他人的意见。使用Windows服务完成此任务非常有意义。

我唯一的指导是避免使用BackgroundWorker进行线程,因为您在Windows服务中执行此操作。 BackgroundWorker类旨在提供有关线程操作进度的反馈。除非您计划让前端应用程序从Windows服务接收反馈,然后将该信息提供给用户(例如,使用进度条),否则BackgroundWorker对象对您所需的内容来说太过分了。我建议使用ThreadPoolThread类,具体取决于您的具体情况。有关选择哪些方面的指导,请参阅指南here