从客户端通过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,但捆绑在任务中,或者用于描述正在进行的操作的任何其他“工具”)。