示例#1
0
        internal void HandleCompleted()
        {
            if (this.IsCompletedInternally && (System.Threading.Interlocked.Exchange(ref this.userNotified, 1) == 0))
            {
                this.abortable = null;
                try
                {
                    if (!Util.DoNotHandleException(this.Failure))
                    {
                        this.CompletedRequest();
                    }
                }
                catch (Exception ex)
                {
                    if (this.HandleFailure(ex))
                    {
                        throw;
                    }
                }
                finally
                {
                    this.userCompleted = true;

                    this.SetAsyncWaitHandle();

                    if ((null != this.userCallback) && !(this.Failure is System.Threading.ThreadAbortException) && !(this.Failure is System.StackOverflowException))
                    {
                        this.userCallback(this);
                    }
                }
            }
        }
示例#2
0
        /// <summary>Set the AsyncWait and invoke the user callback.</summary>
        /// <remarks>
        /// If the background thread gets a ThreadAbort, the userCallback will never be invoked.
        /// This is why it's generally important to never wait forever, but to have more specific
        /// time limit.  Also then cancel the operation, to make sure its stopped, to avoid
        /// multi-threading if your wait time limit was just too short.
        /// </remarks>
        internal void HandleCompleted()
        {
            // Dev10

            if (this.IsCompletedInternally && (System.Threading.Interlocked.Exchange(ref this.userNotified, 1) == 0))
            {
                this.abortable = null; // reset abort via CancelRequest
                try
                {
                    // avoid additional work when aborting for exceptional reasons
                    if (!Util.DoNotHandleException(this.Failure))
                    {
                        // the CompleteRequest may do additional work which is why
                        // it is important not to signal the user via either the
                        // IAsyncResult.IsCompleted, IAsyncResult.WaitHandle or the callback
                        this.CompletedRequest();
                    }
                }
                catch (Exception ex)
                {
                    if (this.HandleFailure(ex))
                    {
                        throw;
                    }
                }
                finally
                {
                    // 1. set IAsyncResult.IsCompleted, otherwise user was
                    // signalled on another thread, but the property may not be true.
                    this.userCompleted = true;

                    // 2. signal the wait handle because it can't be first nor can it be last.
                    //
                    // There is a very small window for race condition between setting the wait handle here and disposing
                    // the wait handle inside EndExecute(). Say thread1 is the async thread that executes up till this point, i.e. right
                    // after userCompleted is set to true and before the asyncWait is signaled; thread2 wakes up and calls EndExecute() till
                    // right before we try to dispose the wait handle; thread3 wakes up and calls AsyncWaitHandle which creates a new instance
                    // for this.asyncWait; thread2 then resumes to dispose this.asyncWait and if at this point thread1 sets this.asyncWait,
                    // we'll get an ObjectDisposedException on thread1.  SetAsyncWaitHandle() will protect this scenario with a critical section.
                    this.SetAsyncWaitHandle();

                    // 3. invoke the callback because user may throw an exception and stop any further processing
                    if ((null != this.userCallback) && !(this.Failure is System.Threading.ThreadAbortException) && !(this.Failure is System.StackOverflowException))
                    {   // any exception thrown by user should be "unhandled"
                        // it's possible callback will be invoked while another creates and sets the asyncWait
                        this.userCallback(this);
                    }
                }
            }
        }
示例#3
0
 internal bool HandleFailure(Exception e)
 {
     System.Threading.Interlocked.CompareExchange(ref this.failure, e, null);
     this.SetCompleted();
     return(Util.DoNotHandleException(e));
 }