C# Windows 带池的服务队列

C# Windows Service queue with Pool

编辑:上下文

我必须开发一个 Web asp.net 应用程序,它允许用户为一个或多个 CAO 文件创建 "Conversion request"。

我的应用程序应该只将文件上传到我可以转换它们的目录。

然后我想要一个服务来检查由 Web 应用程序更新的数据库,以查看转换是否正在等待完成。然后我必须使用一些参数对该文件调用批处理命令。

问题是,如果用户提供错误完成的 CAO 文件,这些转换可能会冻结。在这种情况下,我们希望用户或管理员能够取消转换过程。

用于转换的批处理命令是第三方工具,我无法更改。它需要一个令牌才能转换,只要我有多个可用令牌,我就可以进行多线程处理。另一个应用程序可以同时使用这些令牌,所以我不能根据我拥有的令牌数量只拥有一个预先确定大小的线程池。

我必须知道我是否可以转换的唯一方法是使用命令开始转换并查看日志中是否告诉我我有许可证问题,这意味着 "No token available" 或 "Current licence doesn't accept the given input format"。因为我只允许在网络应用程序上使用可用的输入格式,所以我不会遇到第二个问题。

Web 应用程序几乎完成,我的意思是我可以在最后上传文件并下载结果和转换日志。现在我需要执行将获取输入文件、转换它们、更新数据库中的转换状态并最后将这些文件添加到正确的下载目录中的服务。


我必须处理一项服务,如果某行设置为 "Ready to convert" 或 "Must be canceled".[=12,该服务将以高频率(可能 5 或 10 秒)查看数据库=]

如果该行设置为 "ready to convert",我必须尝试转换它,但我使用第三方 dll 进行转换,该 dll 具有允许我在 atm 上同时进行 5 次转换的许可令牌系统。

如果该行设置为 "Must be canceled" 我必须终止转换,因为它要么冻结并且管理员不得不终止它,要么因为用户取消了他自己的任务。

此外,转换时间可能会很长,从 1 或 2 秒到几个小时不等,具体取决于文件大小及其创建方式。

正如我在这里看到的那样,我正在考虑一个池化系统:

Whosebug answer

池化系统使我能够将读取数据库部分与转换过程隔离开来。但我觉得我失去了对后台进程的一种控制。这也许是正义的,因为我不习惯他们。

但是我不太习惯服务,即使这个池系统看起来不错,我也不知道如果需要我可以取消任何任务?

我用来转换的工具作为一个简单的批处理命令工作,如果现在没有可用的许可证,它只会 return 给我一个错误,但是使用池如何让转换线程等待转换如果没有可用的许可证,要做的是一个简单的无限 while 循环是一个合适的答案吗?这对我来说似乎很糟糕。

最后,我不能只使用“5 线程池”,因为这些许可证也被其他 2 个应用程序使用,这不会让我随时知道有多少可用。

使用 pool 的想法也可能是错误的,正如我所说,我不是很习惯服务,在开始一些愚蠢的事情之前,我更喜欢问 abotu 做这件事的好方法。

另外,关于数据库reading/writing,即使我认为第二种方案更好,我是否应该:

所以我更多的是询问一些关于我应该如何做的建议,而不是纯粹的代码答案,但一些例子可能非常有用。

编辑:更准确地说,我需要找到一种方法:

(目前,我只有一个可用的许可证,如果需要,我会在以后改进它) 有一个 运行 作为循环的服务,如果可能的话,将为给定的请求启动一个新线程。该服务必须仍然是 运行ning,因为状态可以设置为 "Require to be cancel"。

目前我正在考虑一个带有取消令牌的任务。这可能会实现这一目标。

但是如果任务发现令牌当前不可用,我该如何告诉我的服务主循环它现在无法处理?我在考虑只有一个整数值作为 return,其中 return 代码将作为结束原因的指示器:取消/无令牌/结束......这是一个好方法吗?

我听说您的过程中最大的瓶颈是转换...池化/对象映射/直接 sql 听起来不如转换瓶颈重要。

有多种方法可以解决这个问题,具体取决于您的环境和约束条件。又好又快又便宜...选2.

就 "best practice" 而言,有大规模解决方案(ESB、基于消息队列等),也有小规模解决方案(控制台应用程序、批处理文件、Windows 调度程序上的 powershell 脚本等)和中间解决方案(这通常是找到 "Good Enough" 答案的地方)。你需要处理的东西的数量应该决定哪一个最适合你。

无论您在上面选择哪个...

我的第一步将是消除变量...

  • 您要处理多少量?如果你写了一些没有优化但有效的东西,这足以处理你当前的数量吗? (例如,控制台应用程序 运行 每 10 - 15 秒使用 Windows 任务计划程序,如果 运行s 超过 15 分钟就会被杀死)

  • 第三方dll是否支持多线程?如果不是,那将消除所有与多线程相关的问题,并缩小您在如何横向扩展方面的选择范围。

然后您可以确定哪种方法适合您的问题域...

  • 它会是部署在多台机器上的相同服务,每台机器每 10-15 秒访问一次数据库吗?或者
  • 是否会使用多线程在一台机器上提供一项服务?
  • 会不会是其他东西(池化可能会或可能不会)?

得到上面的答案后,下一个问题是。

  • 所需的工作是否符合您项目的分配预算和时间限制?如果不是,请回到上面的问题,看看上面是否有您可以不同回答的问题,这会将此问题的答案更改为是。

希望这些问题能帮助您找到一个好的答案。