首页 > 解决方案 > 在 RunAsync(CancellationToken) 中从客户端手动调用 Cancel

问题描述

在 RunAsync(CancellationToken) 后台方法中,当前代码正在生成新线程,并且在 while(true) 循环中还有一些长时间运行的任务。

Web api 控制器公开提供取消请求,然后使用入队/出队,此请求在 RunAsync(cancellationToken) while(true) 循环中访问。

我只是无法在接收此取消请求的 web api 控制器与传递给 runasync 方法内运行的线程的取消令牌之间建立连接。

RunAsync(cancellationToken) 
{ 
   while(True)
   { 
     new thread(cancellationtoken)
   } 
} 

我很确定的一件事是,用户以某种方式调用的取消请求与作为 RunAsync() 的参数的 cancelToken 之间没有联系,如上面的代码所示。似乎它们没有连接。我们不想在用户取消请求时退出 RunAsync() 后台的永远循环,这仅适用于特定线程运行。
请指导我正确的方向来设计终止线程的取消请求。

标签: azure-service-fabricservice-fabric-statefulservice-fabric-actor

解决方案


正如 Peter Bons 所建议的,传递给 RunAsync 的取消令牌由 Service Fabric 创建和管理,以告知服务它正在关闭。当服务结构想要升级或在节点之间移动服务时,您应该注意这种取消以正常关闭您的服务。

另一点是,您不要取消 CancellationToken,而是取消,因此在这种情况下,您的代码创建的任何线程都应该为每个要单独取消的线程CancellationTokenSource创建自己的,并且必须将由此生成的令牌提供给线程所以它知道什么时候被取消了。CancellationTokenSourceCancellationTokenSource

另一点是,如果你想让它顺利进行,你应该创建一个链接CancellationTokenSource使用CancellationTokenSource.CreateLinkedTokenSource(SFTokenPassedOnRunAsync),这样当 Service Fabric 想要关闭服务时,创建的主取消令牌将取消任何子操作,否则你必须从你的代码中处理。

关于主要问题,您只能在创建 的同一进程中取消操作CancellationTokenSource,更简单的方法是在服务中公开一个端点(通过远程处理或通过 Rest API),它将接收调用,找到令牌并取消手术。

会是这样的:

  • 服务创建CancellationTokenSource并使用生成的令牌启动新线程
  • CancellationTokenSource存储在同一进程内可见的静态变量中,以便 API 可以看到它
  • Api 调用会得到这个CancellationTokenSource并调用Cancel()

如果是正在运行的操作列表(多线程),您可以将 CTS 存储在 Dictionary 中并为每个操作指定 ID,然后您可以根据操作的 ID 找到 CTS。


推荐阅读