高优先级的自定义命令Windows服务 [英] Custom Command Windows Services on HIGH Priority

查看:111
本文介绍了高优先级的自定义命令Windows服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个部署在Windows Server 2008中的Work Tracker WPF应用程序,并且该Tracker应用程序正在通过WACF服务与(Tracker)windows服务通信.

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

因此,每个工作请求都将用来完成工作添加过程.

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

我的解决方法:

我使用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的请求,然后通过检查您从词典中检索到的任务来返回进度.如果任务已完成,他们可以发送请求以获取完成的数据,或者在您的情况下,只需阅读已完成的文件即可.

当他们想要取消时,他们会发送带有UID的请求,然后您可以通过在字典中找到任务并将其告知取消来取消任务.

取消一项工作

在代码内部,您将需要定期检查取消令牌,以查看是否应停止运行代码(请参见 rel ="nofollow noreferrer"> Albahari(如果您使用的是EAP ).到那时,您将退出工作处理,并且如果设计得当,您的代码应在需要的地方处理IDiposable,从内存中删除大字符串等.

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

  • 经过一段长时间的工作(例如,调用外部API)
  • 在您控制的循环(forforeachdowhile)中,检查每次迭代
  • 在很长的顺序代码块中(可能要花费一些时间),您要插入要定期检查的点

您需要定义对取消作出反应的速度-对于Windows服务,它应该在几毫秒内,最好是确保Windows在重新启动或停止服务时没有问题.

有些人使用线程来完成整个过程,并终止线程-这很丑陋,不再推荐了.

可靠性

您需要问:如果服务器重新启动,Windows服务崩溃或发生任何其他异常导致您丢失不完整的作业,将会发生什么?在这种情况下,您可能希望使用可靠的队列体系结构,以便能够重新启动作业或重建尚未开始的作业队列.

如果您不想扩展,这很简单-使用Windows服务在其中存储作业信息的本地数据库.

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

如果您确实想要扩展,或者您的客户端位于多台计算机上,并且您的作业引擎服务器场"具有1台或更多台服务器,则可以考虑使用消息队列,而不是直接使用OnCustomCommand进行通信.

消息队列有很多好处.它们将使您能够可靠地将作业提交到中央队列,然后许多工作人员可以接管并处理这些队列,并使客户端和服务器脱钩,以便您可以扩展作业运行服务.它们用于确保作业以高度分离的方式可靠地提交和处理,并且可以在本地或全局工作,但始终可靠,您甚至可以将其与在可动态扩展的云工作器上运行Windows服务结合起来. /p>

例如MSMQ(如果您想维护自己的防火墙,或者必须保留在自己的防火墙内)等技术,或者企业集成的模式和最佳做法.对于WASB,则有许多(MSDN)许多(用于BrokeredMessaging等的MSDN示例) NuGet软件包供您使用

I have an Work Tracker WPF application which deployed in Windows Server 2008 and this Tracker application is communicating with (Tracker)windows service VIA WCF Service.

User can create any work entry/edit/add/delete/Cancel any work entry from Worker Tracker GUI application. Internally it will send a request to the Windows service. Windows Service will get the work request and process it in multithreading. Each workrequest entry will actually create n number of work files (based on work priority) in a output folder location.

So each work request will take to complete the work addition process.

Now my question is If I cancel the currently creating work entry. I want to to stop the current windows service work in RUNTIME. The current thread which is creating output files for the work should get STOPPED. All the thread should killed. All the thread resources should get removed once the user requested for CANCEL.

My workaround:

I use Windows Service On Custom Command method to send custom values to the windows service on runtime. What I am achieving here is it is processing the current work or current thread (ie creating output files for the work item recieved).and then it is coming to custom command for cancelling the request.

Is there any way so that the Work item request should get stopped once we get the custom command.

Any work around is much appreciated.

解决方案

Summary

You are essentially talking about running a task host for long running tasks, and being able to cancel those tasks. Your specific question seems to want to know the best way to implement this in .NET. Your architecture is good, although you are brave to roll your own rather than using existing frameworks, and you haven't mentioned scaling your architecture later.

My preference is for using the TPL Task object. It supports cancellation, and is easy to poll for progress, etc. You can only use this in .NET 4 onwards.

It is hard to provide code without basically designing a whole job hosting engine for you and knowing your .NET version. I have described the steps in detail below, with references to example code.

Your approach of using the Windows Service OnCustomCommand is fine, you could also use a messaging service (see below) if you have that option for client-service comms. This would be more appropriate for a scenario where you have many clients talking to a central job service, and the job service is not on the same machine as the client.

Running and cancelling tasks on threads

Before we look at your exact context, it would be good to review MSDN - Asynchronous Programming Patterns. There are three main .NET patterns to run and cancel jobs on threads, and I list them in order of preference for use:

  • TAP: Task-based Asynchronous Pattern
    • Based on Task, which has been available only since .NET 4
    • The prefered way to run and control any thread-based activity from .NET 4 onwards
    • Much simpler to implement that EAP
  • EAP: Event-based Asynchronous Pattern
    • Your only option if you don't have .NET 4 or later.
    • Hard to implement, but once you have understood it you can roll it out and it is very reliable to use
  • APM: Asynchronous Programming Model
    • No longer relevant unless you maintain legacy code or use old APIs.
    • Even with .NET 1.1 you can implement a version of EAP, so I will not cover this as you say you are implementing your own solution

The architecture

Imagine this like a REST based service.

  • The client submits a job, and gets returned an identifier for the job
  • A job engine then picks up the job when it is ready, and starts running it
  • If the client doesn't want the job any more, then they delete the job, using it's identifier

This way the client is completely isolated from the workings of the job engine, and the job engine can be improved over time.

The job engine

The approach is as follows:

  • For a submitted task, generate a universal identifier (UID) so that you can:
    • Identify a running task
    • Poll for results
    • Cancel the task if required
  • return that UID to the client
  • queue the job using that identifier
  • when you have resources
    • run the job by creating a Task
    • store the Task in a dictionary against the UID as a key

When the client wants results, they send the request with the UID and you return progress by checking against the Task that you retrieve from the dictionary. If the task is complete they can then send a request for the completed data, or in your case just go and read the completed files.

When they want to cancel they send the request with the UID, and you cancel the Task by finding it in the dictionary and telling it to cancel.

Cancelling inside a job

Inside your code you will need to regularly check your cancellation token to see if you should stop running code (see How do I abort/cancel TPL Tasks? if you are using the TAP pattern, or Albahari if you are using EAP). At that point you will exit your job processing, and your code, if designed well, should dispose of IDiposables where required, remove big strings from memory etc.

The basic premise of cancellation is that you check your cancellation token:

  • After a block of work that takes a long time (e.g. a call to an external API)
  • Inside a loop (for, foreach, do or while) that you control, you check on each iteration
  • Within a long block of sequential code, that might take "some time", you insert points to check on a regular basis

You need to define how quickly you need to react to a cancellation - for a windows service it should be within milliseconds, preferably, to make sure that windows doesn't have problems restarting or stopping the service.

Some people do this whole process with threads, and by terminating the thread - this is ugly and not recommended any more.

Reliability

You need to ask: what happens if your server restarts, the windows service crashes, or any other exception happens causing you to lose incomplete jobs? In this case you may want a queue architecture that is reliable in order to be able to restart jobs, or rebuild the queue of jobs you haven't started yet.

If you don't want to scale, this is simple - use a local database that the windows service stored job information in.

  • On submission of a job, record its details in the database
  • When you start a job, record that against the job record in the database
  • When the client collects the job, mark it for delayed garbage collection in the database, and then delete it after a set amount of time (1 hour, 1 day ...)
  • If your service restarts and there are "in progress jobs" then requeue them and then start your job engine again.

If you do want to scale, or your clients are on many computers, and you have a job engine "farm" of 1 or more servers, then look at using a message queue instead of directly communicating using OnCustomCommand.

Message Queues have multiple benefits. They will allow you to reliably submit jobs to a central queue that many workers can then pick up and process, and to decouple your clients and servers so you can scale out your job running services. They are used to ensure jobs are reliably submitted and processed in a highly decoupled fashion, and this can work locally or globally, but always reliably, you can even then combine it with running your windows service on cloud workers which you can dynamically scale.

Examples of technologies are MSMQ (if you want to maintain your own, or must stay inside your own firewall), or Windows Azure Service Bus (WASB) - which is cheap, and already done for you. In either case you will want to use Patterns and Best Practices for Enterprise Integration. In the case of WASB then there are many (MSDN), many (MSDN samples for BrokeredMessaging etc.), many (new Task-based API) developer resources, and NuGet packages for you to use

这篇关于高优先级的自定义命令Windows服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆