/// <summary>
        /// Registers a callback object. If cancellation has already occurred, the
        /// callback will have been run by the time this method returns.
        /// </summary>
        internal CancellationTokenRegistration InternalRegister(
            Action <object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext executionContext)
        {
            ThrowIfDisposed();

            // the CancellationToken has already checked that the token is cancelable before calling this method.
            Contract.Assert(CanBeCanceled, "Cannot register for uncancelable token src");

            // if not canceled, register the event handlers
            // if canceled already, run the callback synchronously
            // Apart from the semantics of late-enlistment, this also ensures that during ExecuteCallbackHandlers() there
            // will be no mutation of the _registeredCallbacks list

            if (!IsCancellationRequested)
            {
                int myIndex = Thread.CurrentThread.ManagedThreadId % s_nLists;

                CancellationCallbackInfo callbackInfo = new CancellationCallbackInfo(callback, stateForCallback, targetSyncContext, executionContext, this);

                //allocate the callback list array
                if (m_registeredCallbacksLists == null)
                {
                    SparselyPopulatedArray <CancellationCallbackInfo>[] list = new SparselyPopulatedArray <CancellationCallbackInfo> [s_nLists];
                    Interlocked.CompareExchange(ref m_registeredCallbacksLists, list, null);
                }

                //allocate the actual lists on-demand to save mem in low-use situations, and to avoid false-sharing.
                if (m_registeredCallbacksLists[myIndex] == null)
                {
                    SparselyPopulatedArray <CancellationCallbackInfo> callBackArray = new SparselyPopulatedArray <CancellationCallbackInfo>(4);
                    Interlocked.CompareExchange(ref (m_registeredCallbacksLists[myIndex]), callBackArray, null);
                }

                // Now add the registration to the list.
                SparselyPopulatedArray <CancellationCallbackInfo>        callbacks = m_registeredCallbacksLists[myIndex];
                SparselyPopulatedArrayAddInfo <CancellationCallbackInfo> addInfo   = callbacks.Add(callbackInfo);
                CancellationTokenRegistration registration = new CancellationTokenRegistration(this, callbackInfo, addInfo);

                if (!IsCancellationRequested)
                {
                    return(registration);
                }

                //If a cancellation has since come in, we will try to undo the registration and run the callback directly here.
                bool deregisterOccurred = registration.TryDeregister();

                if (!deregisterOccurred)
                {
                    // the callback execution process must have snagged the callback for execution, so
                    // 1. wait for the callback to complete, then
                    // 2. return a dummy registration.
                    WaitForCallbackToComplete(callbackInfo);
                    return(new CancellationTokenRegistration());
                }
            }

            // If cancellation already occurred, we run the callback on this thread and return an empty registration.
            callback(stateForCallback);
            return(new CancellationTokenRegistration());
        }
 internal CancellationTokenRegistration InternalRegister(Action <object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext executionContext)
 {
     this.ThrowIfDisposed();
     if (!this.IsCancellationRequested)
     {
         int index = Thread.CurrentThread.ManagedThreadId % s_nLists;
         CancellationCallbackInfo element = new CancellationCallbackInfo(callback, stateForCallback, targetSyncContext, executionContext, this);
         if (this.m_registeredCallbacksLists == null)
         {
             SparselyPopulatedArray <CancellationCallbackInfo>[] arrayArray = new SparselyPopulatedArray <CancellationCallbackInfo> [s_nLists];
             Interlocked.CompareExchange <SparselyPopulatedArray <CancellationCallbackInfo>[]>(ref this.m_registeredCallbacksLists, arrayArray, null);
         }
         if (this.m_registeredCallbacksLists[index] == null)
         {
             SparselyPopulatedArray <CancellationCallbackInfo> array = new SparselyPopulatedArray <CancellationCallbackInfo>(4);
             Interlocked.CompareExchange <SparselyPopulatedArray <CancellationCallbackInfo> >(ref this.m_registeredCallbacksLists[index], array, null);
         }
         SparselyPopulatedArrayAddInfo <CancellationCallbackInfo> registrationInfo = this.m_registeredCallbacksLists[index].Add(element);
         CancellationTokenRegistration registration = new CancellationTokenRegistration(this, element, registrationInfo);
         if (!this.IsCancellationRequested)
         {
             return(registration);
         }
         if (!registration.TryDeregister())
         {
             this.WaitForCallbackToComplete(element);
             return(new CancellationTokenRegistration());
         }
     }
     callback(stateForCallback);
     return(new CancellationTokenRegistration());
 }
 // Token: 0x06003E40 RID: 15936 RVA: 0x000E71FC File Offset: 0x000E53FC
 internal CancellationTokenRegistration InternalRegister(Action <object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext executionContext)
 {
     if (AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
     {
         this.ThrowIfDisposed();
     }
     if (!this.IsCancellationRequested)
     {
         if (this.m_disposed && !AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
         {
             return(default(CancellationTokenRegistration));
         }
         int num = Thread.CurrentThread.ManagedThreadId % CancellationTokenSource.s_nLists;
         CancellationCallbackInfo cancellationCallbackInfo         = new CancellationCallbackInfo(callback, stateForCallback, targetSyncContext, executionContext, this);
         SparselyPopulatedArray <CancellationCallbackInfo>[] array = this.m_registeredCallbacksLists;
         if (array == null)
         {
             SparselyPopulatedArray <CancellationCallbackInfo>[] array2 = new SparselyPopulatedArray <CancellationCallbackInfo> [CancellationTokenSource.s_nLists];
             array = Interlocked.CompareExchange <SparselyPopulatedArray <CancellationCallbackInfo>[]>(ref this.m_registeredCallbacksLists, array2, null);
             if (array == null)
             {
                 array = array2;
             }
         }
         SparselyPopulatedArray <CancellationCallbackInfo> sparselyPopulatedArray = Volatile.Read <SparselyPopulatedArray <CancellationCallbackInfo> >(ref array[num]);
         if (sparselyPopulatedArray == null)
         {
             SparselyPopulatedArray <CancellationCallbackInfo> value = new SparselyPopulatedArray <CancellationCallbackInfo>(4);
             Interlocked.CompareExchange <SparselyPopulatedArray <CancellationCallbackInfo> >(ref array[num], value, null);
             sparselyPopulatedArray = array[num];
         }
         SparselyPopulatedArrayAddInfo <CancellationCallbackInfo> registrationInfo = sparselyPopulatedArray.Add(cancellationCallbackInfo);
         CancellationTokenRegistration result = new CancellationTokenRegistration(cancellationCallbackInfo, registrationInfo);
         if (!this.IsCancellationRequested)
         {
             return(result);
         }
         if (!result.TryDeregister())
         {
             return(result);
         }
     }
     callback(stateForCallback);
     return(default(CancellationTokenRegistration));
 }
Пример #4
0
 internal CancellationTokenRegistration InternalRegister(Action <object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext executionContext)
 {
     if (AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
     {
         this.ThrowIfDisposed();
     }
     if (!this.IsCancellationRequested)
     {
         if (this.m_disposed && !AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
         {
             return(new CancellationTokenRegistration());
         }
         int index = Thread.CurrentThread.ManagedThreadId % CancellationTokenSource.s_nLists;
         CancellationCallbackInfo cancellationCallbackInfo = new CancellationCallbackInfo(callback, stateForCallback, targetSyncContext, executionContext, this);
         SparselyPopulatedArray <CancellationCallbackInfo>[] sparselyPopulatedArrayArray1 = this.m_registeredCallbacksLists;
         if (sparselyPopulatedArrayArray1 == null)
         {
             SparselyPopulatedArray <CancellationCallbackInfo>[] sparselyPopulatedArrayArray2 = new SparselyPopulatedArray <CancellationCallbackInfo> [CancellationTokenSource.s_nLists];
             sparselyPopulatedArrayArray1 = Interlocked.CompareExchange <SparselyPopulatedArray <CancellationCallbackInfo>[]>(ref this.m_registeredCallbacksLists, sparselyPopulatedArrayArray2, (SparselyPopulatedArray <CancellationCallbackInfo>[])null) ?? sparselyPopulatedArrayArray2;
         }
         SparselyPopulatedArray <CancellationCallbackInfo> sparselyPopulatedArray1 = Volatile.Read <SparselyPopulatedArray <CancellationCallbackInfo> >(ref sparselyPopulatedArrayArray1[index]);
         if (sparselyPopulatedArray1 == null)
         {
             SparselyPopulatedArray <CancellationCallbackInfo> sparselyPopulatedArray2 = new SparselyPopulatedArray <CancellationCallbackInfo>(4);
             Interlocked.CompareExchange <SparselyPopulatedArray <CancellationCallbackInfo> >(ref sparselyPopulatedArrayArray1[index], sparselyPopulatedArray2, (SparselyPopulatedArray <CancellationCallbackInfo>)null);
             sparselyPopulatedArray1 = sparselyPopulatedArrayArray1[index];
         }
         SparselyPopulatedArrayAddInfo <CancellationCallbackInfo> registrationInfo = sparselyPopulatedArray1.Add(cancellationCallbackInfo);
         CancellationTokenRegistration tokenRegistration = new CancellationTokenRegistration(cancellationCallbackInfo, registrationInfo);
         if (!this.IsCancellationRequested || !tokenRegistration.TryDeregister())
         {
             return(tokenRegistration);
         }
     }
     callback(stateForCallback);
     return(new CancellationTokenRegistration());
 }
Пример #5
0
        private void ExecuteCallbackHandlers(bool throwOnFirstException)
        {
            List <Exception> exceptionList = (List <Exception>)null;

            SparselyPopulatedArray <CancellationCallbackInfo>[] sparselyPopulatedArrayArray = this.m_registeredCallbacksLists;
            if (sparselyPopulatedArrayArray == null)
            {
                Interlocked.Exchange(ref this.m_state, 3);
            }
            else
            {
                try
                {
                    for (int index = 0; index < sparselyPopulatedArrayArray.Length; ++index)
                    {
                        SparselyPopulatedArray <CancellationCallbackInfo> sparselyPopulatedArray = Volatile.Read <SparselyPopulatedArray <CancellationCallbackInfo> >(ref sparselyPopulatedArrayArray[index]);
                        if (sparselyPopulatedArray != null)
                        {
                            for (SparselyPopulatedArrayFragment <CancellationCallbackInfo> currArrayFragment = sparselyPopulatedArray.Tail; currArrayFragment != null; currArrayFragment = currArrayFragment.Prev)
                            {
                                for (int currArrayIndex = currArrayFragment.Length - 1; currArrayIndex >= 0; --currArrayIndex)
                                {
                                    this.m_executingCallback = currArrayFragment[currArrayIndex];
                                    if (this.m_executingCallback != null)
                                    {
                                        CancellationCallbackCoreWorkArguments args = new CancellationCallbackCoreWorkArguments(currArrayFragment, currArrayIndex);
                                        try
                                        {
                                            if (this.m_executingCallback.TargetSyncContext != null)
                                            {
                                                this.m_executingCallback.TargetSyncContext.Send(new SendOrPostCallback(this.CancellationCallbackCoreWork_OnSyncContext), (object)args);
                                                this.ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
                                            }
                                            else
                                            {
                                                this.CancellationCallbackCoreWork(args);
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            if (throwOnFirstException)
                                            {
                                                throw;
                                            }
                                            else
                                            {
                                                if (exceptionList == null)
                                                {
                                                    exceptionList = new List <Exception>();
                                                }
                                                exceptionList.Add(ex);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                finally
                {
                    this.m_state             = 3;
                    this.m_executingCallback = (CancellationCallbackInfo)null;
                    Thread.MemoryBarrier();
                }
                if (exceptionList != null)
                {
                    throw new AggregateException((IEnumerable <Exception>)exceptionList);
                }
            }
        }
        /// <summary>
        /// Invoke the Canceled event.
        /// </summary>
        /// <remarks>
        /// The handlers are invoked synchronously in LIFO order.
        /// </remarks>
        private void ExecuteCallbackHandlers(bool throwOnFirstException)
        {
            Contract.Assert(IsCancellationRequested, "ExecuteCallbackHandlers should only be called after setting IsCancellationRequested->true");
            Contract.Assert(ThreadIDExecutingCallbacks != -1, "ThreadIDExecutingCallbacks should have been set.");

            // Design decision: call the delegates in LIFO order so that callbacks fire 'deepest first'.
            // This is intended to help with nesting scenarios so that child enlisters cancel before their parents.
            List <Exception> exceptionList = null;

            SparselyPopulatedArray <CancellationCallbackInfo>[] callbackLists = m_registeredCallbacksLists;

            // If there are no callbacks to run, we can safely exit.  Any races to lazy initialize it
            // will see IsCancellationRequested and will then run the callback themselves.
            if (callbackLists == null)
            {
                Interlocked.Exchange(ref m_state, NOTIFYINGCOMPLETE);
                return;
            }

            try
            {
                for (int index = 0; index < callbackLists.Length; index++)
                {
                    SparselyPopulatedArray <CancellationCallbackInfo> list = callbackLists[index];
                    if (list != null)
                    {
                        SparselyPopulatedArrayFragment <CancellationCallbackInfo> currArrayFragment = list.Tail;

                        while (currArrayFragment != null)
                        {
                            for (int i = currArrayFragment.Length - 1; i >= 0; i--)
                            {
                                // 1a. publish the indended callback, to ensure ctr.Dipose can tell if a wait is necessary.
                                // 1b. transition to the target syncContext and continue there..
                                //  On the target SyncContext.
                                //   2. actually remove the callback
                                //   3. execute the callback
                                // re:#2 we do the remove on the syncCtx so that we can be sure we have control of the syncCtx before
                                //        grabbing the callback.  This prevents a deadlock if ctr.Dispose() might run on the syncCtx too.
                                m_executingCallback = currArrayFragment[i];
                                if (m_executingCallback != null)
                                {
                                    //Transition to the target sync context (if necessary), and continue our work there.
                                    CancellationCallbackCoreWorkArguments args = new CancellationCallbackCoreWorkArguments(currArrayFragment, i);

                                    // marshal exceptions: either aggregate or perform an immediate rethrow
                                    // We assume that syncCtx.Send() has forwarded on user exceptions when appropriate.
                                    try
                                    {
                                        if (m_executingCallback.TargetSyncContext != null)
                                        {
                                            m_executingCallback.TargetSyncContext.Send(CancellationCallbackCoreWork_OnSyncContext, args);
                                            // CancellationCallbackCoreWork_OnSyncContext may have altered ThreadIDExecutingCallbacks, so reset it.
                                            ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
                                        }
                                        else
                                        {
                                            CancellationCallbackCoreWork_OnSyncContext(args);
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        if (throwOnFirstException)
                                        {
                                            throw;
                                        }

                                        // Otherwise, log it and proceed.
                                        if (exceptionList == null)
                                        {
                                            exceptionList = new List <Exception>();
                                        }
                                        exceptionList.Add(ex);
                                    }
                                }
                            }

                            currArrayFragment = currArrayFragment.Prev;
                        }
                    }
                }
            }
            finally
            {
                m_state             = NOTIFYINGCOMPLETE;
                m_executingCallback = null;
                Thread.MemoryBarrier(); // for safety, prevent reorderings crossing this point and seeing inconsistent state.
            }

            if (exceptionList != null)
            {
                Contract.Assert(exceptionList.Count > 0, "Expected exception count > 0");
                throw new AggregateException(exceptionList);
            }
        }
Пример #7
0
        private void ExecuteCallbackHandlers(bool throwOnFirstException)
        {
            List <Exception> list = null;

            SparselyPopulatedArray <CancellationCallbackInfo>[] registeredCallbacksLists = this.m_registeredCallbacksLists;
            if (registeredCallbacksLists == null)
            {
                Interlocked.Exchange(ref this.m_state, 3);
                return;
            }
            try
            {
                for (int i = 0; i < registeredCallbacksLists.Length; i++)
                {
                    SparselyPopulatedArray <CancellationCallbackInfo> sparselyPopulatedArray = Volatile.Read <SparselyPopulatedArray <CancellationCallbackInfo> >(ref registeredCallbacksLists[i]);
                    if (sparselyPopulatedArray != null)
                    {
                        for (SparselyPopulatedArrayFragment <CancellationCallbackInfo> sparselyPopulatedArrayFragment = sparselyPopulatedArray.Tail; sparselyPopulatedArrayFragment != null; sparselyPopulatedArrayFragment = sparselyPopulatedArrayFragment.Prev)
                        {
                            for (int j = sparselyPopulatedArrayFragment.Length - 1; j >= 0; j--)
                            {
                                this.m_executingCallback = sparselyPopulatedArrayFragment[j];
                                if (this.m_executingCallback != null)
                                {
                                    CancellationCallbackCoreWorkArguments cancellationCallbackCoreWorkArguments = new CancellationCallbackCoreWorkArguments(sparselyPopulatedArrayFragment, j);
                                    try
                                    {
                                        if (this.m_executingCallback.TargetSyncContext != null)
                                        {
                                            this.m_executingCallback.TargetSyncContext.Send(new SendOrPostCallback(this.CancellationCallbackCoreWork_OnSyncContext), cancellationCallbackCoreWorkArguments);
                                            this.ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
                                        }
                                        else
                                        {
                                            this.CancellationCallbackCoreWork(cancellationCallbackCoreWorkArguments);
                                        }
                                    }
                                    catch (Exception item)
                                    {
                                        if (throwOnFirstException)
                                        {
                                            throw;
                                        }
                                        if (list == null)
                                        {
                                            list = new List <Exception>();
                                        }
                                        list.Add(item);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            finally
            {
                this.m_state             = 3;
                this.m_executingCallback = null;
                Thread.MemoryBarrier();
            }
            if (list != null)
            {
                throw new AggregateException(list);
            }
        }
        private void ExecuteCallbackHandlers(bool throwOnFirstException)
        {
            List <Exception> innerExceptions = null;

            SparselyPopulatedArray <CancellationCallbackInfo>[] registeredCallbacksLists = this.m_registeredCallbacksLists;
            if (registeredCallbacksLists == null)
            {
                Interlocked.Exchange(ref this.m_state, 3);
            }
            else
            {
                try
                {
                    for (int i = 0; i < registeredCallbacksLists.Length; i++)
                    {
                        SparselyPopulatedArray <CancellationCallbackInfo> array = registeredCallbacksLists[i];
                        if (array != null)
                        {
                            for (SparselyPopulatedArrayFragment <CancellationCallbackInfo> fragment = array.Tail; fragment != null; fragment = fragment.Prev)
                            {
                                for (int j = fragment.Length - 1; j >= 0; j--)
                                {
                                    this.m_executingCallback = fragment[j];
                                    if (this.m_executingCallback != null)
                                    {
                                        CancellationCallbackCoreWorkArguments state = new CancellationCallbackCoreWorkArguments(fragment, j);
                                        try
                                        {
                                            if (this.m_executingCallback.TargetSyncContext != null)
                                            {
                                                this.m_executingCallback.TargetSyncContext.Send(new SendOrPostCallback(this.CancellationCallbackCoreWork_OnSyncContext), state);
                                                this.ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
                                            }
                                            else
                                            {
                                                this.CancellationCallbackCoreWork_OnSyncContext(state);
                                            }
                                        }
                                        catch (Exception exception)
                                        {
                                            if (throwOnFirstException)
                                            {
                                                throw;
                                            }
                                            if (innerExceptions == null)
                                            {
                                                innerExceptions = new List <Exception>();
                                            }
                                            innerExceptions.Add(exception);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                finally
                {
                    this.m_state             = 3;
                    this.m_executingCallback = null;
                    Thread.MemoryBarrier();
                }
                if (innerExceptions != null)
                {
                    throw new AggregateException(innerExceptions);
                }
            }
        }