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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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();
                }
            }
        }