0

使用作为参数传递的 cancelTokenSource 生成一个线程。

RootStatefulService
{
    var cts= new CancellationTokenSource();
    ThreadStart starter = ()=> ParentMethod(Message.Value, cts);

    Thread t = new Thread(starter);
    t.Start();
    ...

    // When there is cancel request from client, below code runs
    cts.Token.Cancel();
}

在此 ParentMethod 中,创建了 Actor 并再次尝试传递 CancellationToken。

ParentMethod(SomeValue value, CancellationTokenSource cts)
{
    var actorWithToken = ActorProxy.Create<IActorWithToken>(
                      actorId,
                      new Uri(ActorWithTokenUrl));

    actorWithToken.StartLongRunningTask(someId, cts);

    cts.Token.Register(() => { StopImmediatelyAndTerminateActor});
}

它是自定义令牌,根据客户端请求,调用 RootStatefulService.cts.Cancel()。从有状态服务到参与者,我不确定是否传递了取消令牌源引用,以便根服务中的 Token.Cancel() 调用向下传播到参与者 Token.Register 方法。我没有成功。如果这不起作用,请回答调用自定义 Token.Cancel() 以传播到生成的演员的正确方法。

4

1 回答 1

0

您不应该创建线程来调用参与者,代理实现对目标参与者服务进行异步调用,您应该使这些调用异步。

您使用的方法有很多缺陷。

  • CancellationTokenSource应该只由一个所有者控制,您应该只将它们传递给CancellationToken被调用的方法。
  • 使用这种方法,您必须通过 via 中止线程,Thread.Abort()但不会向参与者发送取消请求。
  • 如果该方法在等待它完成的操作中没有被阻塞,则actorWithToken.StartLongRunningTask(someId, cts);该方法完成执行并且线程将完成。
  • 当 Cancellation 发生在线程外时,会在不存在的上下文中cts.Token.Register(() => { StopImmediatelyAndTerminateActor});调用该方法,可能会导致许多难以识别的问题StopImmediatelyAndTerminateActor

关于代码,您应该能够像这样进行调用:

var cts = new CancellationTokenSource();

string uri = "fabric:/appName/ActorServiceName";
var actor = ActorProxy.Create<IMyActorInterface>(new ActorId(id), new Uri(uri));
Task<int> actorResut = actor.GetCountAsync(cts.Token);

//here you can manage what you want to do
//You could get the result like
var count = await actorResut;

//you can check if it has completed like this
if(actorResut.IsCompleted) {}

//you can cancel the task calling cancel on CTS
cts.Cancel();

对于长期运行的操作,这种方法有一些注意事项:

  • 只有调用者可以取消操作,因为它锁定了对调用者的调用,并且它必须处于活动状态才能取消远程操作。如果取消请求来自 API,您的请求必须始终发送到启动操作的同一实例,并且在大多数情况下,不能保证在负载均衡器后面发生并且您有许多实例正在运行。
  • 一个actor操作有一个超时,这个超时可以在操作完成之前取消操作,可以通过设置增加
  • Actor 运行时中有一些重试逻辑,当一个操作失败时它会重试,你可以得到重复的处理请求。
于 2018-11-06T12:31:09.607 回答