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

Nul*_*nce 5 .net c# wcf nettcpbinding long-running-processes

我有一个设置为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

            }

}
Run Code Online (Sandbox Code Playgroud)

我想这里的问题是,每次呼叫到达服务器时,它都被视为新请求.

那么如何在WCF中启动和取消长时间运行的任务呢?

编辑:我将它作为Windows服务托管

Ste*_*ary 5

我有一个设置为PerCall的WCF服务

......这里的问题是,每次呼叫到达服务器时,都会将其视为新请求.

是的,这正是你要告诉它的事情.如果可以,只需改为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并在队列上删除消息以取消处理.所有其他逻辑都移动到后端服务.

  • @Aron是对的.我的意思是`static ConcurrentDictionary <Guid,CancellationTokenSource>`. (2认同)