Interrupt Actor - пользовательский токен отмены, исходящий от родительского сервиса - PullRequest
0 голосов
/ 02 ноября 2018

Поток порождается с cancellationTokenSource, переданным в качестве аргумента.

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 создается Актер, который снова пытается передать 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 () для распространения вниз к порожденному актеру.

1 Ответ

0 голосов
/ 06 ноября 2018

Вы не должны создавать потоки для вызова актеров, реализация прокси-сервера делает асинхронные вызовы целевой службе актера, вместо этого вы должны делать эти вызовы асинхронными.

Подход, который вы использовали, имеет много недостатков.

  • 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();

Существуют некоторые предостережения при таком подходе для длительных операций:

  • Только вызывающий абонент может отменить операцию, поскольку он блокирует вызов вызывающего абонента и должен быть активен, чтобы отменить удаленную операцию. В случае, если запрос на отмену исходит от API, ваши запросы должны всегда направляться в тот же экземпляр, который инициировал операцию, и в большинстве случаев не гарантируется, что он выполняется за балансировщиком нагрузки, и у вас много запущенных экземпляров.
  • У актерской операции есть тайм-аут, этот тайм-аут может отменить операцию до ее завершения, вы можете увеличить ее с помощью настроек
  • В среде выполнения актера есть некоторая логика повторения, при неудачной попытке выполнения операции вы можете получить повторяющиеся запросы на обработку.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...