public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state) { if (instance == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNoServiceObject))); } if (inputs == null) { if (this.InputParameterCount > 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceNull, this.InputParameterCount))); } } else if (inputs.Length != this.InputParameterCount) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceInvalid, this.InputParameterCount, inputs.Length))); } this.outputs = EmptyArray.Allocate(this.OutputParameterCount); AsyncMethodInvoker.StartOperationInvokePerformanceCounters(this.taskMethod.Name); IAsyncResult returnValue; bool callFailed = true; bool callFaulted = false; ServiceModelActivity activity = null; try { Activity boundActivity = null; AsyncMethodInvoker.CreateActivityInfo(ref activity, ref boundActivity); AsyncMethodInvoker.StartOperationInvokeTrace(this.taskMethod.Name); using (boundActivity) { if (DiagnosticUtility.ShouldUseActivity) { string activityName = SR.GetString(SR.ActivityExecuteMethod, this.taskMethod.DeclaringType.FullName, this.taskMethod.Name); ServiceModelActivity.Start(activity, activityName, ActivityType.ExecuteUserCode); } object taskReturnValue = this.InvokeDelegate(instance, inputs, this.outputs); if (taskReturnValue == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("task"); } else if (this.isGenericTask) { returnValue = (IAsyncResult)this.toAsyncMethodInfo.Invoke(null, new object[] { taskReturnValue, callback, state }); } else { returnValue = ((Task)taskReturnValue).AsAsyncResult(callback, state); } callFailed = false; } } catch (System.Security.SecurityException e) { DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(AuthorizationBehavior.CreateAccessDeniedFaultException()); } catch (Exception e) { TraceUtility.TraceUserCodeException(e, this.taskMethod); if (e is FaultException) { callFaulted = true; callFailed = false; } throw; } finally { ServiceModelActivity.Stop(activity); // Any exception above means InvokeEnd will not be called, so complete it here. if (callFailed || callFaulted) { AsyncMethodInvoker.StopOperationInvokeTrace(callFailed, callFaulted, this.TaskMethod.Name); AsyncMethodInvoker.StopOperationInvokePerformanceCounters(callFailed, callFaulted, this.TaskMethod.Name); } } return(returnValue); }
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); } }
internal DispatchOperationRuntime(DispatchOperation operation, ImmutableDispatchRuntime parent) { if (operation == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("operation"); } if (parent == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parent"); } if (operation.Invoker == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("RuntimeRequiresInvoker0"))); } this.disposeParameters = operation.AutoDisposeParameters && !operation.HasNoDisposableParameters; this.parent = parent; this.callContextInitializers = EmptyArray <ICallContextInitializer> .ToArray(operation.CallContextInitializers); this.inspectors = EmptyArray <IParameterInspector> .ToArray(operation.ParameterInspectors); this.faultFormatter = operation.FaultFormatter; this.impersonation = operation.Impersonation; this.deserializeRequest = operation.DeserializeRequest; this.serializeReply = operation.SerializeReply; this.formatter = operation.Formatter; this.invoker = operation.Invoker; try { this.isSynchronous = operation.Invoker.IsSynchronous; } catch (Exception exception) { if (Fx.IsFatal(exception)) { throw; } throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(exception); } this.isTerminating = operation.IsTerminating; this.action = operation.Action; this.name = operation.Name; this.releaseInstanceAfterCall = operation.ReleaseInstanceAfterCall; this.releaseInstanceBeforeCall = operation.ReleaseInstanceBeforeCall; this.replyAction = operation.ReplyAction; this.isOneWay = operation.IsOneWay; this.transactionAutoComplete = operation.TransactionAutoComplete; this.transactionRequired = operation.TransactionRequired; this.receiveContextAcknowledgementMode = operation.ReceiveContextAcknowledgementMode; this.bufferedReceiveEnabled = operation.BufferedReceiveEnabled; this.isInsideTransactedReceiveScope = operation.IsInsideTransactedReceiveScope; if ((this.formatter == null) && (this.deserializeRequest || this.serializeReply)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("DispatchRuntimeRequiresFormatter0", new object[] { this.name }))); } if ((operation.Parent.InstanceProvider == null) && (operation.Parent.Type != null)) { SyncMethodInvoker invoker = this.invoker as SyncMethodInvoker; if (invoker != null) { this.ValidateInstanceType(operation.Parent.Type, invoker.Method); } AsyncMethodInvoker invoker2 = this.invoker as AsyncMethodInvoker; if (invoker2 != null) { this.ValidateInstanceType(operation.Parent.Type, invoker2.BeginMethod); this.ValidateInstanceType(operation.Parent.Type, invoker2.EndMethod); } } }
private async Task <Tuple <object, object[]> > InvokeAsync(object instance, object[] inputs) { EnsureIsInitialized(); if (instance == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNoServiceObject))); } if (inputs == null) { if (this.inputParameterCount > 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceNull, this.inputParameterCount))); } } else if (inputs.Length != this.inputParameterCount) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceInvalid, this.inputParameterCount, inputs.Length))); } object[] outputs = EmptyArray.Allocate(this.outputParameterCount); AsyncMethodInvoker.StartOperationInvokePerformanceCounters(this.taskMethod.Name); object returnValue; ServiceModelActivity activity = null; Activity boundActivity = null; try { AsyncMethodInvoker.CreateActivityInfo(ref activity, ref boundActivity); AsyncMethodInvoker.StartOperationInvokeTrace(this.taskMethod.Name); if (DiagnosticUtility.ShouldUseActivity) { string activityName = SR.GetString(SR.ActivityExecuteMethod, this.taskMethod.DeclaringType.FullName, this.taskMethod.Name); ServiceModelActivity.Start(activity, activityName, ActivityType.ExecuteUserCode); } OperationContext.EnableAsyncFlow(); returnValue = this.invokeDelegate(instance, inputs, outputs); if (returnValue == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("task"); } var returnValueTask = returnValue as Task; if (returnValueTask != null) { // Only return once the task has completed await returnValueTask; } return(Tuple.Create(returnValue, outputs)); } catch (SecurityException e) { DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(AuthorizationBehavior.CreateAccessDeniedFaultException()); } catch (Exception e) { TraceUtility.TraceUserCodeException(e, this.taskMethod); throw; } finally { OperationContext.DisableAsyncFlow(); if (boundActivity != null) { ((IDisposable)boundActivity).Dispose(); } ServiceModelActivity.Stop(activity); } }