Esempio n. 1
0
        public override object Execute(ControllerContext controllerContext, IDictionary <string, object> parameters)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }

            // Performance sensitive so avoid Linq or delegates.
            ParameterInfo[] parameterInfos  = MethodInfo.GetParameters();
            object[]        parametersArray = new object[parameterInfos.Length];
            for (int i = 0; i < parameterInfos.Length; i++)
            {
                ParameterInfo parameterInfo = parameterInfos[i];
                object        parameter     = ExtractParameterFromDictionary(parameterInfo, parameters, MethodInfo);
                parametersArray[i] = parameter;
            }

            ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(MethodInfo);
            object actionReturnValue          = dispatcher.Execute(controllerContext.Controller, parametersArray);

            return(actionReturnValue);
        }
        public override IAsyncResult BeginExecute(ControllerContext controllerContext, IDictionary <string, object> parameters, AsyncCallback callback, object state)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }

            AsyncManager asyncManager = GetAsyncManager(controllerContext.Controller);

            BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState) {
                // call the XxxAsync() method
                ParameterInfo[] parameterInfos     = AsyncMethodInfo.GetParameters();
                var             rawParameterValues = from parameterInfo in parameterInfos
                                                     select ExtractParameterFromDictionary(parameterInfo, parameters, AsyncMethodInfo);

                object[] parametersArray = rawParameterValues.ToArray();

                TriggerListener   listener    = new TriggerListener();
                SimpleAsyncResult asyncResult = new SimpleAsyncResult(asyncState);

                // hook the Finished event to notify us upon completion
                Trigger finishTrigger = listener.CreateTrigger();
                asyncManager.Finished += delegate { finishTrigger.Fire(); };
                asyncManager.OutstandingOperations.Increment();

                // to simplify the logic, force the rest of the pipeline to execute in an asynchronous callback
                listener.SetContinuation(() => ThreadPool.QueueUserWorkItem(_ => asyncResult.MarkCompleted(false /* completedSynchronously */, asyncCallback)));

                // the inner operation might complete synchronously, so all setup work has to be done before this point
                ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(AsyncMethodInfo);
                dispatcher.Execute(controllerContext.Controller, parametersArray); // ignore return value from this method

                // now that the XxxAsync() method has completed, kick off any pending operations
                asyncManager.OutstandingOperations.Decrement();
                listener.Activate();
                return(asyncResult);
            };

            EndInvokeDelegate <object> endDelegate = delegate(IAsyncResult asyncResult) {
                // call the XxxCompleted() method
                ParameterInfo[] completionParametersInfos    = CompletedMethodInfo.GetParameters();
                var             rawCompletionParameterValues = from parameterInfo in completionParametersInfos
                                                               select ExtractParameterOrDefaultFromDictionary(parameterInfo, asyncManager.Parameters);

                object[] completionParametersArray = rawCompletionParameterValues.ToArray();

                ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(CompletedMethodInfo);
                object actionReturnValue          = dispatcher.Execute(controllerContext.Controller, completionParametersArray);
                return(actionReturnValue);
            };

            return(AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _executeTag, asyncManager.Timeout));
        }
Esempio n. 3
0
        public override object Execute(ControllerContext context, IDictionary <string, object> parameters)
        {
            Precondition.Require(context, () => Error.ArgumentNull("context"));
            Precondition.Require(parameters, () => Error.ArgumentNull("parameters"));

            object[] parameterValues = _method.GetParameters()
                                       .Select(p => ExtractParameter(p, parameters, _method))
                                       .ToArray();

            return(DispatcherCache.GetDispatcher(_method).Execute(context.Controller, parameterValues));
        }
        public override IAsyncResult BeginExecute(ControllerContext context,
                                                  IDictionary <string, object> parameters, AsyncCallback callback, object state)
        {
            Precondition.Require(context, () => Error.ArgumentNull("context"));
            Precondition.Require(parameters, () => Error.ArgumentNull("parameters"));

            AsyncManager asyncManager = GetAsyncManager(context.Controller);

            BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState) {
                object[] parameterValues = _entryMethod.GetParameters()
                                           .Select(p => ExtractParameter(p, parameters, _entryMethod))
                                           .ToArray();

                TriggerListener listener    = new TriggerListener();
                MvcAsyncResult  asyncResult = new MvcAsyncResult(asyncState);

                Trigger finishTrigger = listener.CreateTrigger();
                asyncManager.Finished += delegate {
                    finishTrigger.Fire();
                };
                asyncManager.OutstandingOperations.Increment();
                listener.SetContinuation(() => ThreadPool.QueueUserWorkItem(_ =>
                                                                            asyncResult.MarkCompleted(false, asyncCallback)));

                DispatcherCache.GetDispatcher(_entryMethod)
                .Execute(context.Controller, parameterValues);

                asyncManager.OutstandingOperations.Decrement();
                listener.Activate();

                return(asyncResult);
            };

            EndInvokeDelegate <object> endDelegate = delegate(IAsyncResult asyncResult) {
                object[] parameterValues = _completedMethod.GetParameters()
                                           .Select(p => ExtractParameter(p, parameters, _completedMethod))
                                           .ToArray();

                return(DispatcherCache.GetDispatcher(_completedMethod)
                       .Execute(context.Controller, parameterValues));
            };

            return(AsyncResultWrapper.Begin(callback, state, beginDelegate,
                                            endDelegate, _executeTag, asyncManager.Timeout));
        }
Esempio n. 5
0
        public override IAsyncResult BeginExecute(ControllerContext controllerContext, IDictionary <string, object> parameters, AsyncCallback callback, object state)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }

            ParameterInfo[]      parameterInfos     = BeginMethod.GetParameters();
            IEnumerable <object> rawParameterValues = from parameterInfo in parameterInfos
                                                      select ExtractParameterFromDictionary(parameterInfo, parameters, BeginMethod);

            List <object> parametersList = rawParameterValues.Take(parameterInfos.Length - 2).ToList();

            MethodDispatcher beginDispatcher = DispatcherCache.GetDispatcher(BeginMethod);
            MethodDispatcher endDispatcher   = DispatcherCache.GetDispatcher(EndMethod);

            // need to add callback + state object to list
            BeginInvokeCallback beginCallback = (innerCallback, innerState) => {
                parametersList.Add(innerCallback);
                parametersList.Add(innerState);
                object[] parametersArray = parametersList.ToArray();

                IAsyncResult innerAsyncResult = (IAsyncResult)beginDispatcher.Execute(controllerContext.Controller, parametersArray);
                return(innerAsyncResult);
            };

            AsyncCallback <object> endCallback = ar => {
                object actionReturnValue = endDispatcher.Execute(controllerContext.Controller, new object[] { ar });
                return(actionReturnValue);
            };

            // Set the timeout and go
            IAsyncManagerContainer helperContainer = controllerContext.Controller as IAsyncManagerContainer;
            int timeout = (helperContainer != null) ? helperContainer.AsyncManager.Timeout : Timeout.Infinite;

            return(AsyncResultWrapper.WrapWithTimeout(callback, state, beginCallback, endCallback, timeout, _executeTag));
        }
Esempio n. 6
0
        public override object Execute(ControllerContext controllerContext, IDictionary <string, object> parameters)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }

            ParameterInfo[] parameterInfos     = MethodInfo.GetParameters();
            var             rawParameterValues = from parameterInfo in parameterInfos
                                                 select ExtractParameterFromDictionary(parameterInfo, parameters, MethodInfo);

            object[] parametersArray = rawParameterValues.ToArray();

            ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(MethodInfo);
            object actionReturnValue          = dispatcher.Execute(controllerContext.Controller, parametersArray);

            return(actionReturnValue);
        }
        public override IAsyncResult BeginExecute(ControllerContext controllerContext, IDictionary <string, object> parameters, AsyncCallback callback, object state)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }

            ParameterInfo[] parameterInfos     = TaskMethodInfo.GetParameters();
            var             rawParameterValues = from parameterInfo in parameterInfos
                                                 select ExtractParameterFromDictionary(parameterInfo, parameters, TaskMethodInfo);

            object[] parametersArray = rawParameterValues.ToArray();

            CancellationTokenSource tokenSource = null;
            bool  disposedTimer              = false;
            Timer taskCancelledTimer         = null;
            bool  taskCancelledTimerRequired = false;

            int timeout = GetAsyncManager(controllerContext.Controller).Timeout;

            for (int i = 0; i < parametersArray.Length; i++)
            {
                if (default(CancellationToken).Equals(parametersArray[i]))
                {
                    tokenSource        = new CancellationTokenSource();
                    parametersArray[i] = tokenSource.Token;

                    // If there is a timeout we will create a timer to cancel the task when the
                    // timeout expires.
                    taskCancelledTimerRequired = timeout > Timeout.Infinite;
                    break;
                }
            }

            ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(TaskMethodInfo);

            if (taskCancelledTimerRequired)
            {
                taskCancelledTimer = new Timer(_ =>
                {
                    lock (tokenSource)
                    {
                        if (!disposedTimer)
                        {
                            tokenSource.Cancel();
                        }
                    }
                }, state: null, dueTime: timeout, period: Timeout.Infinite);
            }

            Task   taskUser            = dispatcher.Execute(controllerContext.Controller, parametersArray) as Task;
            Action cleanupAtEndExecute = () =>
            {
                // Cleanup code that's run in EndExecute, after we've waited on the task value.

                if (taskCancelledTimer != null)
                {
                    // Timer callback may still fire after Dispose is called.
                    taskCancelledTimer.Dispose();
                }

                if (tokenSource != null)
                {
                    lock (tokenSource)
                    {
                        disposedTimer = true;
                        tokenSource.Dispose();
                        if (tokenSource.IsCancellationRequested)
                        {
                            // Give Timeout exceptions higher priority over other exceptions, mainly OperationCancelled exceptions
                            // that were signaled with out timeout token.
                            throw new TimeoutException();
                        }
                    }
                }
            };

            TaskWrapperAsyncResult result = new TaskWrapperAsyncResult(taskUser, state, cleanupAtEndExecute);

            // if user supplied a callback, invoke that when their task has finished running.
            if (callback != null)
            {
                if (taskUser.IsCompleted)
                {
                    // If the underlying task is already finished, from our caller's perspective this is just
                    // a synchronous completion.
                    result.CompletedSynchronously = true;
                    callback(result);
                }
                else
                {
                    // If the underlying task isn't yet finished, from our caller's perspective this will be
                    // an asynchronous completion. We'll use ContinueWith instead of Finally for two reasons:
                    //
                    // - Finally propagates the antecedent Task's exception, which we don't need to do here.
                    //   Out caller will eventually call EndExecute, which correctly observes the
                    //   antecedent Task's exception anyway if it faulted.
                    //
                    // - Finally invokes the callback on the captured SynchronizationContext, which is
                    //   unnecessary when using APM (Begin / End). APM assumes that the callback is invoked
                    //   on an arbitrary ThreadPool thread with no SynchronizationContext set up, so
                    //   ContinueWith gets us closer to the desired semantic.
                    result.CompletedSynchronously = false;
                    taskUser.ContinueWith(_ =>
                    {
                        callback(result);
                    });
                }
            }

            return(result);
        }
Esempio n. 8
0
        public override IAsyncResult BeginExecute(ControllerContext controllerContext, IDictionary <string, object> parameters, AsyncCallback callback, object state)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }

            ParameterInfo[] parameterInfos     = TaskMethodInfo.GetParameters();
            var             rawParameterValues = from parameterInfo in parameterInfos
                                                 select ExtractParameterFromDictionary(parameterInfo, parameters, TaskMethodInfo);

            object[] parametersArray = rawParameterValues.ToArray();

            CancellationTokenSource tokenSource = null;
            bool  disposedTimer              = false;
            Timer taskCancelledTimer         = null;
            bool  taskCancelledTimerRequired = false;

            int timeout = GetAsyncManager(controllerContext.Controller).Timeout;

            for (int i = 0; i < parametersArray.Length; i++)
            {
                if (default(CancellationToken).Equals(parametersArray[i]))
                {
                    tokenSource        = new CancellationTokenSource();
                    parametersArray[i] = tokenSource.Token;

                    // If there is a timeout we will create a timer to cancel the task when the
                    // timeout expires.
                    taskCancelledTimerRequired = timeout > Timeout.Infinite;
                    break;
                }
            }

            ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(TaskMethodInfo);

            if (taskCancelledTimerRequired)
            {
                taskCancelledTimer = new Timer(_ =>
                {
                    lock (tokenSource)
                    {
                        if (!disposedTimer)
                        {
                            tokenSource.Cancel();
                        }
                    }
                }, state: null, dueTime: timeout, period: Timeout.Infinite);
            }

            Task   taskUser            = dispatcher.Execute(controllerContext.Controller, parametersArray) as Task;
            Action cleanupAtEndExecute = () =>
            {
                // Cleanup code that's run in EndExecute, after we've waited on the task value.

                if (taskCancelledTimer != null)
                {
                    // Timer callback may still fire after Dispose is called.
                    taskCancelledTimer.Dispose();
                }

                if (tokenSource != null)
                {
                    lock (tokenSource)
                    {
                        disposedTimer = true;
                        tokenSource.Dispose();
                        if (tokenSource.IsCancellationRequested)
                        {
                            // Give Timeout exceptions higher priority over other exceptions, mainly OperationCancelled exceptions
                            // that were signaled with out timeout token.
                            throw new TimeoutException();
                        }
                    }
                }
            };

            TaskWrapperAsyncResult result = new TaskWrapperAsyncResult(taskUser, state, cleanupAtEndExecute);

            // if user supplied a callback, invoke that when their task has finished running.
            if (callback != null)
            {
                taskUser.Finally(() =>
                {
                    callback(result);
                });
            }

            return(result);
        }
        public override IAsyncResult BeginExecute(ControllerContext controllerContext, IDictionary <string, object> parameters, AsyncCallback callback, object state)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }

            AsyncManager    asyncHelper         = GetAsyncManager(controllerContext.Controller);
            SingleFireEvent setupCompletedEvent = new SingleFireEvent();

            BeginInvokeCallback beginCallback = (innerCallback, innerState) => {
                ManualAsyncResult asyncResult = new ManualAsyncResult()
                {
                    AsyncState = innerState
                };

                // Get parameters for async setup method, then execute
                ParameterInfo[] setupParametersInfos    = SetupMethod.GetParameters();
                var             rawSetupParameterValues = from parameterInfo in setupParametersInfos
                                                          select ExtractParameterFromDictionary(parameterInfo, parameters, SetupMethod);

                object[] setupParametersArray = rawSetupParameterValues.ToArray();

                // to simplify the logic, force an asynchronous callback
                asyncHelper.OutstandingOperations.Completed += delegate {
                    if (setupCompletedEvent.Signal())
                    {
                        ThreadPool.QueueUserWorkItem(o => {
                            asyncResult.MarkCompleted(false /* completedSynchronously */, innerCallback);
                        });
                    }
                };

                MethodDispatcher setupDispatcher = DispatcherCache.GetDispatcher(SetupMethod);
                asyncHelper.OutstandingOperations.Increment();
                setupDispatcher.Execute(controllerContext.Controller, setupParametersArray);
                asyncHelper.OutstandingOperations.Decrement();
                return(asyncResult);
            };

            AsyncCallback <object> endCallback = ar => {
                if (setupCompletedEvent.Signal())
                {
                    // the setup method did not complete before this callback executed
                    throw new InvalidOperationException(MvcResources.AsyncActionDescriptor_EndExecuteCalledPrematurely);
                }

                // Get parameters for action method, then execute
                ParameterInfo[] completionParametersInfos    = CompletionMethod.GetParameters();
                var             rawCompletionParameterValues = from parameterInfo in completionParametersInfos
                                                               select ExtractParameterOrDefaultFromDictionary(parameterInfo, asyncHelper.Parameters);

                object[] completionParametersArray = rawCompletionParameterValues.ToArray();

                MethodDispatcher completionDispatcher = DispatcherCache.GetDispatcher(CompletionMethod);
                object           actionReturnValue    = completionDispatcher.Execute(controllerContext.Controller, completionParametersArray);
                return(actionReturnValue);
            };

            // Set the timeout and go
            int timeout = asyncHelper.Timeout;

            return(AsyncResultWrapper.WrapWithTimeout(callback, state, beginCallback, endCallback, timeout, _executeTag));
        }