public override object EndExecute(IAsyncResult asyncResult) { TaskWrapperAsyncResult wrapperResult = (TaskWrapperAsyncResult)asyncResult; // Throw an exception with the correct call stack try { wrapperResult.Task.ThrowIfFaulted(); } finally { if (wrapperResult.CleanupThunk != null) { wrapperResult.CleanupThunk(); } } // Extract the result of the task if there is a result return(_taskValueExtractors.GetOrAdd(TaskMethodInfo.ReturnType, CreateTaskValueExtractor)(wrapperResult.Task)); }
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); }
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"); } 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"); } 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; }