public static Task <bool> GracefulStop(this ActorRef target, TimeSpan timeout, object stopMessage) { var internalTarget = target.AsInstanceOf <InternalActorRef>(); if (internalTarget.IsTerminated) { return(Task.Run(() => true)); } var provider = Futures.ResolveProvider(target); var promise = new TaskCompletionSource <object>(); //set up the timeout var cancellationSource = new CancellationTokenSource(); cancellationSource.Token.Register(() => promise.TrySetCanceled()); cancellationSource.CancelAfter(timeout); //create a new tempcontainer path var path = provider.TempPath(); //callback to unregister from tempcontainer Action unregister = () => provider.UnregisterTempActor(path); var fref = new FutureActorRef(promise, ActorRef.NoSender, unregister, path); internalTarget.Tell(new Watch(internalTarget, fref)); target.Tell(stopMessage, ActorRef.NoSender); return(promise.Task.ContinueWith(t => { var returnResult = false; PatternMatch.Match(t.Result) .With <Terminated>(terminated => { returnResult = (terminated.ActorRef.Path.Equals(target.Path)); }) .Default(m => { returnResult = false; }); internalTarget.Tell(new Unwatch(target, fref)); return returnResult; }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent)); }
public static Task<bool> GracefulStop(this IActorRef target, TimeSpan timeout, object stopMessage) { var internalTarget = target.AsInstanceOf<IInternalActorRef>(); if (internalTarget.IsTerminated) return Task.Run(() => true); var provider = Futures.ResolveProvider(target); var promise = new TaskCompletionSource<object>(); //set up the timeout var cancellationSource = new CancellationTokenSource(); cancellationSource.Token.Register(() => promise.TrySetCanceled()); cancellationSource.CancelAfter(timeout); //create a new tempcontainer path var path = provider.TempPath(); //callback to unregister from tempcontainer Action unregister = () => provider.UnregisterTempActor(path); var fref = new FutureActorRef(promise, unregister, path); internalTarget.Tell(new Watch(internalTarget, fref)); target.Tell(stopMessage, ActorRefs.NoSender); return promise.Task.ContinueWith(t => { var returnResult = false; PatternMatch.Match(t.Result) .With<Terminated>(terminated => { returnResult = (terminated.ActorRef.Path.Equals(target.Path)); }) .Default(m => { returnResult = false; }); internalTarget.Tell(new Unwatch(target, fref)); return returnResult; }, TaskContinuationOptions.ExecuteSynchronously); }
private static Task <object> Ask(ICanTell self, ActorRef replyTo, object message, ActorRefProvider provider, TimeSpan?timeout) { var result = new TaskCompletionSource <object>(); if (timeout.HasValue) { var cancellationSource = new CancellationTokenSource(); cancellationSource.Token.Register(() => result.TrySetCanceled()); cancellationSource.CancelAfter(timeout.Value); } //create a new tempcontainer path ActorPath path = provider.TempPath(); //callback to unregister from tempcontainer Action unregister = () => provider.UnregisterTempActor(path); var future = new FutureActorRef(result, replyTo, unregister, path); //The future actor needs to be registered in the temp container provider.RegisterTempActor(future, path); self.Tell(message, future); return(result.Task); }
private static async Task <object> Ask(ICanTell self, Func <IActorRef, object> messageFactory, IActorRefProvider provider, TimeSpan?timeout, CancellationToken cancellationToken) { TaskCompletionSource <object> result; if (isRunContinuationsAsynchronouslyAvailable) { result = new TaskCompletionSource <object>((TaskCreationOptions)RunContinuationsAsynchronously); } else { result = new TaskCompletionSource <object>(); } CancellationTokenSource timeoutCancellation = null; timeout = timeout ?? provider.Settings.AskTimeout; var ctrList = new List <CancellationTokenRegistration>(2); if (timeout != Timeout.InfiniteTimeSpan && timeout.Value > default(TimeSpan)) { timeoutCancellation = new CancellationTokenSource(); ctrList.Add(timeoutCancellation.Token.Register(() => { result.TrySetException(new AskTimeoutException($"Timeout after {timeout} seconds")); })); timeoutCancellation.CancelAfter(timeout.Value); } if (cancellationToken.CanBeCanceled) { ctrList.Add(cancellationToken.Register(() => result.TrySetCanceled())); } //create a new tempcontainer path ActorPath path = provider.TempPath(); var future = new FutureActorRef(result, () => { }, path, isRunContinuationsAsynchronouslyAvailable); //The future actor needs to be registered in the temp container provider.RegisterTempActor(future, path); var message = messageFactory(future); self.Tell(message, future); try { return(await result.Task); } finally { //callback to unregister from tempcontainer provider.UnregisterTempActor(path); for (var i = 0; i < ctrList.Count; i++) { ctrList[i].Dispose(); } if (timeoutCancellation != null) { timeoutCancellation.Dispose(); } } }