简体   繁体   English

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

[英]Cancel a long running task over WCF from client

I have a WCF service set to PerCall 我有一个设置为PerCall的WCF服务

I would like to know how I can send a Start call from the client to start a long running process, and send a Cancel command to cancel it 我想知道如何从客户端发送一个Start调用以启动一个长时间运行的进程,并发送一个Cancel命令来取消它

My WCF service looks something like this 我的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

            }

}

I guess the problem here is that, each time a call comes to the server, it's treated as a new request. 我想这里的问题是,每次呼叫到达服务器时,它都被视为新请求。

So how should starting and cancelling a long running task in WCF be done? 那么如何在WCF中启动和取消长时间运行的任务呢?

EDIT: I'm hosting it as a windows service 编辑:我将它作为Windows服务托管

I have a WCF service set to PerCall 我有一个设置为PerCall的WCF服务

... the problem here is that, each time a call comes to the server, it's treated as a new request. ......这里的问题是,每次呼叫到达服务器时,都会将其视为新请求。

Yup, that's exactly what you're telling it to do. 是的,这正是你要告诉它的事情。 If you can, just change to InstanceContextMode.PerSession ; 如果可以,只需更改为InstanceContextMode.PerSession ; then you can do what you're trying to do (assuming you're self-hosting). 那么你可以做你想做的事情(假设你是自托管的)。

If you can't do this, then you'll have to develop a more complex solution like @PeterRitchie commented. 如果你不能这样做,那么你将不得不开发一个更复杂的解决方案,如@PeterRitchie评论。 First, your host: IIS is not designed to have long-running operations independent of requests, so I'll assume you're self-hosting. 首先,您的主机:IIS不是设计为独立于请求的长期运行操作,所以我假设您是自托管的。 Next, you'll need a form of token (like a GUID) that will act as an identifier for a long-running operation. 接下来,您将需要一种令牌形式(如GUID),它将充当长时间运行的操作的标识符。 Your Start method will allocate a GUID and CancellationTokenSource and start the operation, and your Stop method will take a GUID and use that to look up the CancellationTokenSource and cancel the operation. 您的Start方法将分配GUID和CancellationTokenSource并启动操作,您的Stop方法将采用GUID并使用它来查找CancellationTokenSource并取消操作。 You'll need a shared (static, threadsafe) dictionary to act as lookup. 您需要一个共享(静态,线程安全)字典来充当查找。

If your host is IIS, then your solution gets more complex... :) 如果您的主机 IIS,那么您的解决方案会变得更复杂...... :)

First, you'll need a backend that's not hosted in IIS. 首先,您需要一个不在IIS中托管的后端。 Common choices are an Azure worker role or a Win32 service. 常见的选择是Azure辅助角色或Win32服务。 Next, you'll need a reliable communications mechanism: an Azure queue, MSMQ, WebSphere, etc. Then you can build your WCF-over-IIS service to have the Start method generate a GUID identifier and drop a message on the queue to start processing. 接下来,您将需要一个可靠的通信机制:Azure队列,MSMQ,WebSphere等。然后,您可以构建您的WCF-over-IIS服务,以使Start方法生成GUID标识符并在队列中删除消息以启动处理。 The Stop method takes the GUID and drops a message on the queue to cancel processing. Stop方法获取GUID并在队列上删除消息以取消处理。 All other logic gets moved to the backend service. 所有其他逻辑都移动到后端服务。

From how you've asked, the client seems to be aware of the async nature of the request. 根据您的询问,客户似乎意识到请求的异步性质。

@StephenCleary and @PeterRitchie's points are excellent, but your first step is to re-do your service/contract to properly implement an async service and add the means of communicating back (to client) some information/handle to the long running operation. @StephenCleary和@PeterRitchie的观点非常好,但您的第一步是重新执行您的服务/合同以正确实施异步服务,并添加向客户端传达一些信息/处理长时间运行操作的方法。

The Framework contains several paradigms for asynchronous programming (already :-) )but when it comes to WCF, you kinda fall back to How to: Implement an Asynchronous Service Operation 框架包含几种异步编程范例(已经:-))但是当谈到WCF时,你又回到了如何:实现异步服务操作

That will provide some infrastructure, but not necessarily the ability to automatically cancel an operation. 这将提供一些基础设施,但不一定能够自动取消操作。

Speaking strictly about the cancellation (as this is your question): you will have to extend whatever your solution ends up being for cancellation. 严格说明取消(因为这是您的问题):您必须延长您的解决方案最终取消的任何内容。 At the minimum you need to add necessary logic to your service “worker” to monitor and honor the cancellation token. 您至少需要向服务“worker”添加必要的逻辑,以监视和兑现取消令牌。

Other considerations that you may expect to encounter: return result from cancellation; 您可能会遇到的其他注意事项:取消结果; cancelling a task that has managed to complete (what of you updated the 1,000,000 records by the time the cancellation request came); 取消已设法完成的任务(在取消请求到来之前,您更新了1,000,000条记录); exception handling (with task-based programming exceptions are not thrown, but bundled in the Task, or whatever other “vehicle” you use to describe the ongoing operation). 异常处理(基于任务的编程异常不会被抛出,但捆绑在任务中,或者用于描述正在进行的操作的任何其他“工具”)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM