自定义命令Windows服务高优先级



我有一个部署在Windows Server 2008中的工作跟踪器WPF应用程序,这个跟踪器应用程序通过WCF服务与(跟踪器)Windows服务通信。

用户可以从Worker Tracker GUI应用程序创建任何工作条目/编辑/添加/删除/取消任何工作条目。在内部,它将向Windows服务发送请求。Windows Service将获取工作请求并以多线程方式处理它。每个工作请求条目实际上将在输出文件夹位置创建n个工作文件(基于工作优先级)。

因此,每个工作请求都需要完成工作添加过程。

现在我的问题是,如果我取消当前创建的工作条目。我想在RUNTIME中停止当前的windows服务工作。正在为工作创建输出文件的当前线程应该被停止。所有的线都应该被杀死。一旦用户请求CANCEL,所有线程资源都应该被删除。

我的解决方案:

我使用Windows Service On Custom Command方法在运行时向Windows Service发送自定义值。我在这里实现的是它正在处理当前工作或当前线程(即为收到的工作项创建输出文件)。然后是取消请求的自定义命令。

是否有任何方法使工作项请求在我们获得自定义命令后停止?

任何解决方法都非常感谢。

总结

你实际上是在谈论为长时间运行的任务运行一个任务主机,并且能够取消这些任务。你的具体问题似乎想知道在。net中实现这一点的最佳方法。您的体系结构很好,尽管您勇敢地推出了自己的框架,而不是使用现有的框架,并且您没有提到以后扩展您的体系结构。

我倾向于使用TPL Task对象。它支持取消,并且很容易轮询进度等。你只能在。net 4以后使用它。

如果不为你设计一个完整的作业托管引擎,不知道你的。net版本,就很难提供代码。我在下面详细描述了这些步骤,并引用了示例代码。

你使用Windows Service OnCustomCommand的方法是好的,你也可以使用消息传递服务(见下文),如果你有客户端服务通信的选项。这将更适合于这样的场景:您有许多客户端与中央作业服务通信,并且作业服务与客户端不在同一台机器上。

正在运行和取消线程上的任务

在我们查看您的确切上下文之前,最好先回顾一下MSDN -异步编程模式。有三种主要的。net模式可以在线程上运行和取消作业,我按照使用的优先顺序列出它们:

  • TAP:基于任务的异步模式
    • 基于任务,从。net 4开始才可用
    • 从。net 4开始运行和控制任何基于线程的活动的首选方式
    • 实现EAP要简单得多
  • EAP:基于事件的异步模式
    • 如果你没有。net 4或更高版本,你唯一的选择。
    • 很难实现,但一旦你理解了它,你就可以推出它,使用
    • 是非常可靠的
  • APM:异步编程模型
    • 不再相关除非您维护遗留代码或使用旧的api。
    • 即使使用。net 1.1,你也可以实现一个版本的EAP,所以我不会在你说你正在实现你自己的解决方案时讨论这个

架构

想象这是一个基于REST的服务。

  • 客户端提交作业,并获得作业的标识符
  • 作业引擎然后在作业准备好时拾取作业,并开始运行它
  • 如果客户端不再需要该作业,则使用其标识符
  • 删除该作业。

通过这种方式,客户端与作业引擎的工作完全隔离,并且可以随着时间的推移改进作业引擎。

作业引擎

方法如下:

  • 对于提交的任务,生成一个通用标识符(UID),以便您可以:
    • 标识正在运行的任务
    • 轮询结果
    • 如果需要取消任务
  • 将UID返回给客户端
  • 使用该标识符将作业排队
  • 当你有资源时
    • 通过创建任务
    • 运行作业
    • 将任务存储在字典中,以UID作为键

当客户端需要结果时,它们发送带有UID的请求,您通过检查从字典中检索到的Task来返回进度。如果任务完成了,他们就可以发送一个请求来获取完成的数据,或者在你的情况下,直接去读取完成的文件。

当他们想要取消时,他们发送带有UID的请求,您通过在字典中找到它并告诉它取消来取消任务。

作业内部取消

在你的代码中,你需要定期检查你的取消令牌,看看你是否应该停止运行代码(参见我如何中止/取消TPL任务?如果您使用TAP模式,或者如果您使用EAP,则使用Albahari模式)。此时,您将退出作业处理,并且您的代码,如果设计良好,应该在需要的地方处理IDiposables,从内存中删除大字符串等。

取消的基本前提是您检查您的取消令牌:

  • 在一个需要很长时间的工作块之后(例如调用外部API)
  • 在您控制的循环(for,foreach,dowhile)中,您检查每次迭代
  • 在一长段顺序代码中,这可能需要"一些时间",您插入点以定期检查

你需要定义你需要多快的反应取消-对于一个windows服务,它应该在毫秒内,最好,以确保窗口没有问题重新启动或停止服务。

有些人使用线程来完成整个过程,并通过终止线程来完成——这很难看,不建议再这样做了。

你需要问:如果你的服务器重新启动,windows服务崩溃,或任何其他异常发生导致你失去未完成的工作,会发生什么?在这种情况下,您可能需要一个可靠的队列体系结构,以便能够重新启动作业,或重新构建尚未启动的作业队列。

如果你不想扩展,这很简单-使用本地数据库,windows服务存储的作业信息。

  • 在提交作业时,在数据库
  • 中记录其详细信息
  • 当您启动作业时,将其记录在数据库
  • 中的作业记录中
  • 当客户端收集作业时,在数据库中将其标记为延迟垃圾收集,然后在设定的时间(1小时,1天…)后将其删除
  • 如果您的服务重新启动并且有"正在进行的作业";然后将它们排队,然后再次启动作业引擎。

如果您确实想要扩展,或者您的客户端在多台计算机上,并且您有一个作业引擎"farm"如果有1台或多台服务器,那么考虑使用消息队列而不是直接使用OnCustomCommand进行通信。

消息队列有很多好处。它们将允许您可靠地将作业提交到中央队列,然后许多工作人员可以提取和处理,并将客户端和服务器解耦,以便您可以扩展运行作业的服务。它们被用来确保作业以一种高度解耦的方式可靠地提交和处理,这可以在本地或全局工作,但总是可靠的,你甚至可以将它与在云工作者上运行你的windows服务结合起来,你可以动态扩展。

技术的例子是MSMQ(如果你想维护你自己的,或者必须留在你自己的防火墙),或Windows Azure服务总线(WASB) -这是便宜的,已经为你做了。无论哪种情况,您都希望使用企业集成模式和最佳实践。对于WASB,有许多(MSDN)、许多(BrokeredMessaging的MSDN示例等)、许多(新的基于任务的API)开发人员资源和NuGet包供您使用

最新更新