Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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);
            }
        }