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));
        }
Beispiel #2
0
        public void MethodInfoProperty()
        {
            // Arrange
            MethodInfo             original   = typeof(object).GetMethod("ToString");
            ActionMethodDispatcher dispatcher = new ActionMethodDispatcher(original);

            // Act
            MethodInfo returned = dispatcher.MethodInfo;

            // Assert
            Assert.Same(original, returned);
        }
        public void GetDispatcher()
        {
            // Arrange
            MethodInfo methodInfo             = typeof(object).GetMethod("ToString");
            ActionMethodDispatcherCache cache = new ActionMethodDispatcherCache();

            // Act
            ActionMethodDispatcher dispatcher1 = cache.GetDispatcher(methodInfo);
            ActionMethodDispatcher dispatcher2 = cache.GetDispatcher(methodInfo);

            // Assert
            Assert.Same(methodInfo, dispatcher1.MethodInfo);
            Assert.Same(dispatcher1, dispatcher2);
        }
        public void ExecuteWithStaticActionMethod()
        {
            // Arrange
            DispatcherController controller = new DispatcherController();
            object[] parameters = new object[0];
            MethodInfo methodInfo = typeof(DispatcherController).GetMethod("StaticAction");
            ActionMethodDispatcher dispatcher = new ActionMethodDispatcher(methodInfo);

            // Act
            object returnValue = dispatcher.Execute(controller, parameters);

            // Assert
            var intResult = Assert.IsType<int>(returnValue);
            Assert.Equal(89, intResult);
        }
Beispiel #5
0
        public void ExecuteWithStaticActionMethod()
        {
            // Arrange
            DispatcherController controller = new DispatcherController();

            object[]               parameters = new object[0];
            MethodInfo             methodInfo = typeof(DispatcherController).GetMethod("StaticAction");
            ActionMethodDispatcher dispatcher = new ActionMethodDispatcher(methodInfo);

            // Act
            object returnValue = dispatcher.Execute(controller, parameters);

            // Assert
            var intResult = Assert.IsType <int>(returnValue);

            Assert.Equal(89, intResult);
        }
        public void ExecuteWithVoidActionMethod()
        {
            // Arrange
            DispatcherController controller = new DispatcherController();
            object[] parameters = new object[] { 5, "some string", new DateTime(2001, 1, 1) };
            MethodInfo methodInfo = typeof(DispatcherController).GetMethod("VoidAction");
            ActionMethodDispatcher dispatcher = new ActionMethodDispatcher(methodInfo);

            // Act
            object returnValue = dispatcher.Execute(controller, parameters);

            // Assert
            Assert.Null(returnValue);
            Assert.Equal(5, controller._i);
            Assert.Equal("some string", controller._s);
            Assert.Equal(new DateTime(2001, 1, 1), controller._dt);
        }
Beispiel #7
0
        public void ExecuteWithVoidActionMethod()
        {
            // Arrange
            DispatcherController controller = new DispatcherController();

            object[]               parameters = new object[] { 5, "some string", new DateTime(2001, 1, 1) };
            MethodInfo             methodInfo = typeof(DispatcherController).GetMethod("VoidAction");
            ActionMethodDispatcher dispatcher = new ActionMethodDispatcher(methodInfo);

            // Act
            object returnValue = dispatcher.Execute(controller, parameters);

            // Assert
            Assert.Null(returnValue);
            Assert.Equal(5, controller._i);
            Assert.Equal("some string", controller._s);
            Assert.Equal(new DateTime(2001, 1, 1), controller._dt);
        }
        public void ExecuteWithStaticActionMethod()
        {
            // Arrange
            DispatcherController controller = new DispatcherController();

            object[]               parameters = new object[0];
            MethodInfo             methodInfo = typeof(DispatcherController).GetMethod("StaticAction");
            ActionMethodDispatcher dispatcher = new ActionMethodDispatcher(methodInfo);

            // Act
            object returnValue = dispatcher.Execute(controller, parameters);

            // Assert
            Assert.IsInstanceOfType(returnValue, typeof(int));
            int intResult = (int)returnValue;

            Assert.AreEqual(89, intResult);
        }
        public void ExecuteWithNormalActionMethod()
        {
            // Arrange
            DispatcherController controller = new DispatcherController();
            object[] parameters = new object[] { 5, "some string", new DateTime(2001, 1, 1) };
            MethodInfo methodInfo = typeof(DispatcherController).GetMethod("NormalAction");
            ActionMethodDispatcher dispatcher = new ActionMethodDispatcher(methodInfo);

            // Act
            object returnValue = dispatcher.Execute(controller, parameters);

            // Assert
            var stringResult = Assert.IsType<string>(returnValue);
            Assert.Equal("Hello from NormalAction!", stringResult);

            Assert.Equal(5, controller._i);
            Assert.Equal("some string", controller._s);
            Assert.Equal(new DateTime(2001, 1, 1), controller._dt);
        }
Beispiel #10
0
        public void ExecuteWithNormalActionMethod()
        {
            // Arrange
            DispatcherController controller = new DispatcherController();

            object[]               parameters = new object[] { 5, "some string", new DateTime(2001, 1, 1) };
            MethodInfo             methodInfo = typeof(DispatcherController).GetMethod("NormalAction");
            ActionMethodDispatcher dispatcher = new ActionMethodDispatcher(methodInfo);

            // Act
            object returnValue = dispatcher.Execute(controller, parameters);

            // Assert
            var stringResult = Assert.IsType <string>(returnValue);

            Assert.Equal("Hello from NormalAction!", stringResult);

            Assert.Equal(5, controller._i);
            Assert.Equal("some string", controller._s);
            Assert.Equal(new DateTime(2001, 1, 1), controller._dt);
        }
        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);
        }
Beispiel #12
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 void MethodInfoProperty()
        {
            // Arrange
            MethodInfo original = typeof(object).GetMethod("ToString");
            ActionMethodDispatcher dispatcher = new ActionMethodDispatcher(original);

            // Act
            MethodInfo returned = dispatcher.MethodInfo;

            // Assert
            Assert.Same(original, returned);
        }