我将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服务托管
答案 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条记录);异常处理(不抛出基于任务的编程异常,但捆绑在任务中,或者用于描述正在进行的操作的任何其他“工具”)。