使用作为参数传递的cancellingTokenSource生成线程。
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()向下传播到生成的actor。
答案 0 :(得分:0)
您不应创建线程来调用actor,代理实现应异步调用目标actor服务,而应使这些调用异步。
您使用的方法有很多缺陷。
CancellationTokenSource
应该仅由一个所有者控制,您只应将其CancellationToken
传递给被调用的方法。Thread.Abort()
中止线程,但不向参与者发送取消请求。actorWithToken.StartLongRunningTask(someId, cts);
操作中被阻塞以等待其完成,则该方法将完成执行,并且线程将完成。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();
这种方法对于长时间运行的操作有一些警告: