public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result) { object returnVal; bool callFailed = true; bool callFaulted = false; ServiceModelActivity activity = null; if (instance == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNoServiceObject))); } try { Activity boundOperation = null; AsyncMethodInvoker.GetActivityInfo(ref activity, ref boundOperation); using (boundOperation) { Task task = result as Task; Fx.Assert(task != null, "InvokeEnd needs to be called with the result returned from InvokeBegin."); if (task.IsFaulted) { Fx.Assert(task.Exception != null, "Task.IsFaulted guarantees non-null exception."); // If FaultException is thrown, we will get 'callFaulted' behavior below. // Any other exception will retain 'callFailed' behavior. throw FxTrace.Exception.AsError <FaultException>(task.Exception); } // Task cancellation without an exception indicates failure but we have no // additional information to provide. Accessing Task.Result will throw a // TaskCanceledException. For consistency between void Tasks and Task<T>, // we detect and throw here. if (task.IsCanceled) { throw FxTrace.Exception.AsError(new TaskCanceledException(task)); } outputs = this.outputs; if (this.isGenericTask) { returnVal = this.taskTResultGetMethod.Invoke(result, Type.EmptyTypes); } else { returnVal = null; } callFailed = false; } } catch (SecurityException e) { DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(AuthorizationBehavior.CreateAccessDeniedFaultException()); } catch (FaultException) { callFaulted = true; callFailed = false; throw; } finally { ServiceModelActivity.Stop(activity); AsyncMethodInvoker.StopOperationInvokeTrace(callFailed, callFaulted, this.TaskMethod.Name); AsyncMethodInvoker.StopOperationInvokePerformanceCounters(callFailed, callFaulted, this.TaskMethod.Name); } return(returnVal); }
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result) { if (instance == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNoServiceObject))); } object returnVal = null; bool callFailed = true; bool callFaulted = false; ServiceModelActivity activity = null; Activity boundOperation = null; try { AsyncMethodInvoker.GetActivityInfo(ref activity, ref boundOperation); Task <Tuple <object, object[]> > invokeTask = result as Task <Tuple <object, object[]> >; if (invokeTask == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.SFxInvalidCallbackIAsyncResult)); } AggregateException ae = null; Tuple <object, object[]> tuple = null; Task task = null; if (invokeTask.IsFaulted) { Fx.Assert(invokeTask.Exception != null, "Task.IsFaulted guarantees non-null exception."); ae = invokeTask.Exception; } else { Fx.Assert(invokeTask.IsCompleted, "Task.Result is expected to be completed"); tuple = invokeTask.Result; task = tuple.Item1 as Task; if (task == null) { outputs = tuple.Item2; return(null); } if (task.IsFaulted) { Fx.Assert(task.Exception != null, "Task.IsFaulted guarantees non-null exception."); ae = task.Exception; } } if (ae != null && ae.InnerException != null) { if (ae.InnerException is FaultException) { // If invokeTask.IsFaulted we produce the 'callFaulted' behavior below. // Any other exception will retain 'callFailed' behavior. callFaulted = true; callFailed = false; } if (ae.InnerException is SecurityException) { DiagnosticUtility.TraceHandledException(ae.InnerException, TraceEventType.Warning); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(AuthorizationBehavior.CreateAccessDeniedFaultException()); } invokeTask.GetAwaiter().GetResult(); } // Task cancellation without an exception indicates failure but we have no // additional information to provide. Accessing Task.Result will throw a // TaskCanceledException. For consistency between void Tasks and Task<T>, // we detect and throw here. if (task.IsCanceled) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TaskCanceledException(task)); } outputs = tuple.Item2; returnVal = this.isGenericTask ? this.taskTResultGetMethod.Invoke(task, Type.EmptyTypes) : null; callFailed = false; return(returnVal); } finally { if (boundOperation != null) { ((IDisposable)boundOperation).Dispose(); } ServiceModelActivity.Stop(activity); AsyncMethodInvoker.StopOperationInvokeTrace(callFailed, callFaulted, this.TaskMethod.Name); AsyncMethodInvoker.StopOperationInvokePerformanceCounters(callFailed, callFaulted, this.TaskMethod.Name); } }