从客户端通过WCF取消长时间运行的任务
我有一个设置为PerCall的WCF服务
我想知道如何从客户端发送一个Start调用以启动一个长时间运行的进程,并发送一个Cancel命令来取消它
我的WCF服务看起来像这样
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] public class Service1 : IService1 { CancellationTokenSource cancelToken = new CancellationTokenSource(); public void Start() { var compute = Task.Factory.StartNew(StartLongRunningTask, cancelToken.Token); } public void Stop() { cancelToken.Cancel(); } private void StartLongRunningTask() { //process here } }
我想这里的问题是,每次呼叫到达服务器时,都会将其视为新请求。
那么如何在WCF中启动和取消长时间运行的任务呢?
编辑:我将它作为Windows服务托管
我有一个设置为PerCall的WCF服务
…这里的问题是,每次呼叫到达服务器时,都会将其视为新请求。
是的,这正是你要告诉它的事情。 如果可以,只需更改为InstanceContextMode.PerSession
; 那么你可以做你想做的事情(假设你是自托管的)。
如果你不能这样做,那么你将不得不开发一个更复杂的解决方案,如@PeterRitchie评论。 首先,你的主机:IIS不是设计为独立于请求的长期运行操作,所以我假设你是自托管的。 接下来,您将需要一种令牌forms(如GUID),它将充当长时间运行的操作的标识符。 您的Start
方法将分配GUID和CancellationTokenSource
并启动操作,您的Stop
方法将获取GUID并使用它来查找CancellationTokenSource
并取消操作。 您需要一个共享(静态,线程安全)字典来充当查找。
如果您的主机是 IIS,那么您的解决方案会变得更复杂…… 🙂
首先,您需要一个不在IIS中托管的后端。 常见的选择是Azure辅助角色或Win32服务。 接下来,您将需要一个可靠的通信机制:Azure队列,MSMQ,WebSphere等。然后,您可以构建您的WCF-over-IIS服务,以使Start
方法生成GUID标识符并在队列上删除消息以启动处理。 Stop
方法获取GUID并在队列上删除消息以取消处理。 所有其他逻辑都被移动到后端服务。
根据您的询问,客户似乎意识到请求的异步性质。
@StephenCleary和@PeterRitchie的观点非常好,但您的第一步是重新执行您的服务/合同以正确实现异步服务,并添加回传(向客户端)一些信息/处理长时间运行操作的方法。
框架包含几种异步编程范例(已经:-))但是当谈到WCF时,你又回到了如何:实现异步服务操作
这将提供一些基础设施,但不一定能够自动取消操作。
严格说明取消(因为这是您的问题):您必须延长您的解决方案最终取消的任何内容。 您至少需要向服务“worker”添加必要的逻辑,以监控和兑现取消令牌。
您可能会遇到的其他注意事项:取消取消结果; 取消已设法完成的任务(在取消请求到来之前,您更新了1,000,000条记录); exception处理(不抛出基于任务的编程exception,但捆绑在任务中,或者用于描述正在进行的操作的任何其他“工具”)。