从客户端通过WCF取消长时间运行的任务

时间:2013-03-10 17:06:14

标签: c# .net wcf nettcpbinding long-running-processes

我将WCF服务设置为PerCall

我想知道如何从客户端发送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服务托管

2 个答案:

答案 0 :(得分:5)

  

我将WCF服务设置为PerCall

     

......问题在于,每次呼叫到达服务器时,都会将其视为新请求。

是的,这正是你要告诉它的事情。如果可以,只需更改为InstanceContextMode.PerSession;那么你可以做你想做的事情(假设你是自托管的)。

如果你不能这样做,那么你将不得不开发一个更复杂的解决方案,如@PeterRitchie评论。首先,您的主机:IIS不是设计为独立于请求的长期运行操作,所以我假设您是自托管的。接下来,您将需要一种令牌形式(如GUID),它将充当长时间运行的操作的标识符。您的Start方法将分配GUID和CancellationTokenSource并开始操作,您的Stop方法将获取GUID并使用该方法查找CancellationTokenSource并取消操作。您需要一个共享(静态,线程安全)字典来充当查找。

如果您的主机 IIS,那么您的解决方案会变得更复杂......:)

首先,您需要一个不在IIS中托管的后端。常见的选择是Azure辅助角色或Win32服务。接下来,您将需要一个可靠的通信机制:Azure队列,MSMQ,WebSphere等。然后,您可以构建您的WCF-over-IIS服务,以使Start方法生成GUID标识符并删除消息队列开始处理。 Stop方法获取GUID并在队列上删除消息以取消处理。所有其他逻辑都被移动到后端服务。

答案 1 :(得分:2)

根据您的询问,客户似乎意识到请求的异步性质。

@StephenCleary和@PeterRitchie的观点非常好,但您的第一步是重新执行您的服务/合同以正确实施异步服务并添加回传(向客户端)一些信息/处理长期运行的方法操作

框架包含几种异步编程范例(已经:-))但是当谈到WCF时,你又回到了How to: Implement an Asynchronous Service Operation

这将提供一些基础设施,但不一定能够自动取消操作。

严格说明取消(因为这是您的问题):您必须延长您的解决方案最终取消的任何内容。您至少需要向服务“worker”添加必要的逻辑,以监视和兑现取消令牌。

您可能会遇到的其他注意事项:取消取消结果;取消已设法完成的任务(在取消请求到来之前,您更新了1,000,000条记录);异常处理(不抛出基于任务的编程异常,但捆绑在任务中,或者用于描述正在进行的操作的任何其他“工具”)。