示例#1
0
        /// <summary>Estimate child ops</summary>
        /// <exception cref="Exception">On error</exception>
        protected override void InnerEstimate()
        {
            StructList2 <Exception> errors = new StructList2 <Exception>();

            foreach (IOperation op in Ops)
            {
                try
                {
                    // Assert session is not cancelled
                    if (session.CancelSrc.IsCancellationRequested)
                    {
                        SetState(OperationState.Cancelled); return;
                    }
                    op.Estimate();
                    if (op.TotalLength > 0L)
                    {
                        this.TotalLength += op.TotalLength;
                    }
                    if (op.Progress > 0L)
                    {
                        this.Progress += op.Progress;
                    }
                    this.CanRollback &= op.CanRollback | op.EffectivePolicy.HasFlag(OperationPolicy.EstimateOnRun);
                }
                catch (Exception e) when(session.Policy.HasFlag(OperationPolicy.BatchContinueOnError))
                {
                    errors.Add(e);
                }
            }
            // Throw captured exceptions
            if (errors.Count > 0)
            {
                throw new AggregateException(errors.ToArray());
            }
        }
 /// <summary>
 /// Dispose enumerable and capture errors
 /// </summary>
 /// <param name="disposableObjects">list of disposables</param>
 /// <param name="disposeErrors">list to be created if errors occur</param>
 public static void DisposeAndCapture(ref StructList2 <IDisposable> disposableObjects, ref StructList4 <Exception> disposeErrors)
 {
     // Dispose disposables
     for (int i = 0; i < disposableObjects.Count; i++)
     {
         IDisposable disposable = disposableObjects[i];
         if (disposable != null)
         {
             try
             {
                 disposable.Dispose();
             }
             catch (AggregateException ae)
             {
                 foreach (Exception e in ae.InnerExceptions)
                 {
                     disposeErrors.Add(e);
                 }
             }
             catch (Exception e)
             {
                 // Capture error
                 disposeErrors.Add(e);
             }
         }
     }
 }
示例#3
0
        /// <summary>
        /// Process the non-dispose. Used when <see cref="nonDisposable"/> is true (singleton instances).
        ///
        /// This may be called from <see cref="Dispose"/> or from the dispose of the last
        /// belate handle (After <see cref="Dispose"/> has been called aswell).
        ///
        /// Only one thread may process the dispose. Returns state back to 0.
        ///
        /// Unattaches all disposables, disposes them, and calls <see cref="InnerDispose(ref StructList4{Exception})"/>.
        /// Does not set state
        /// </summary>
        /// <exception cref="AggregateException">thrown if disposing threw errors</exception>
        protected virtual void ProcessNonDispose()
        {
            // Revert state
            Interlocked.CompareExchange(ref disposing, 0L, 1L);

            // Extract snapshot, clear array
            StructList2 <IDisposable> toDispose = default;

            lock (m_disposelist_lock) { toDispose = disposeList; disposeList = default; }

            // Captured errors
            StructList4 <Exception> disposeErrors = new StructList4 <Exception>();

            // Dispose disposables
            DisposeList.DisposeAndCapture(ref toDispose, ref disposeErrors);

            // Call InnerDispose(). Capture errors to compose it with others.
            try
            {
                InnerDispose(ref disposeErrors);
            }
            catch (Exception e)
            {
                // Capture error
                disposeErrors.Add(e);
            }

            // Throw captured errors
            if (disposeErrors.Count > 0)
            {
                throw new AggregateException(disposeErrors);
            }
        }
        /// <summary>
        /// Process the actual dispose. This may be called from Dispose() or from the dispose of the last
        /// belate handle (After Dispose() has been called aswell).
        ///
        /// Disposes all attached diposables and call <see cref="InnerDispose(ref StructList4{Exception})"/>.
        ///
        /// Only one thread may process the dispose.
        /// Sets state to 2, and then 3.
        ///
        /// Unattaches all disposables, disposes them, and calls <see cref="InnerDispose(ref StructList4{Exception})"/>.
        /// </summary>
        /// <exception cref="AggregateException">thrown if disposing threw errors</exception>
        protected virtual void ProcessDispose()
        {
            // Set state IsDisposing=2, but let only one thread continue.
            bool thisThreadChangedStateToDispose = (Interlocked.CompareExchange(ref disposing, 2L, 0L) == 0L) || (Interlocked.CompareExchange(ref disposing, 2L, 1L) == 1L);

            // Not for this thread.
            if (!thisThreadChangedStateToDispose)
            {
                return;
            }

            // Extract snapshot, clear array
            StructList2 <IDisposable> toDispose = default;

            lock (m_disposelist_lock) { toDispose = disposeList; disposeList = default; }

            // Captured errors
            StructList4 <Exception> disposeErrors = new StructList4 <Exception>();

            // Dispose disposables
            DisposeAndCapture(ref toDispose, ref disposeErrors);

            // Call InnerDispose(). Capture errors to compose it with others.
            try
            {
                InnerDispose(ref disposeErrors);
            }
            catch (Exception e)
            {
                // Capture error
                disposeErrors.Add(e);
            }

            // Call InnerDisposeUnmanaged(). Capture errors to compose it with others.
            try
            {
                InnerDisposeUnmanaged(ref disposeErrors);
            }
            catch (Exception e)
            {
                // Capture error
                disposeErrors.Add(e);
            }

            // Is disposed
            Interlocked.CompareExchange(ref disposing, 3L, 2L);

            // Throw captured errors
            if (disposeErrors.Count > 0)
            {
                throw new AggregateException(disposeErrors);
            }
        }
        /// <summary>
        /// Create a token that combins a pair of tokens.
        /// Removes null values.
        /// </summary>
        /// <param name="token1"></param>
        /// <param name="token2"></param>
        public TokenList(IToken token1, IToken token2)
        {
            StructList2 <IToken> list = new StructList2 <IToken>();

            if (token1 != null)
            {
                list.Add(token1);
            }
            if (token2 != null)
            {
                list.Add(token2);
            }
            this.tokens = list.ToArray();
        }
示例#6
0
        /// <summary>Run child ops</summary>
        protected override void InnerRun()
        {
            StructList2 <Exception> errors = new StructList2 <Exception>();
            long progressReminder          = this.Progress;

            foreach (OperationBase op in Ops)
            {
                if (op.CurrentState == OperationState.Completed)
                {
                    continue;
                }
                if (op.CurrentState == OperationState.Skipped)
                {
                    continue;
                }
                try
                {
                    // Assert session is not cancelled
                    if (session.CancelSrc.IsCancellationRequested)
                    {
                        SetState(OperationState.Cancelled); return;
                    }
                    // Run op
                    op.Run();
                    //
                    if (!EffectivePolicy.HasFlag(OperationPolicy.BatchContinueOnError) && op.CurrentState == OperationState.Error)
                    {
                        throw new AggregateException(op.Errors);
                    }
                    // Move progress
                    if (op.Progress > 0L)
                    {
                        this.Progress += op.Progress;
                    }
                    if (op.TotalLength > 0L)
                    {
                        this.TotalLength += op.TotalLength;
                    }

                    if (op.Progress > 0L || op.TotalLength > 0L)
                    {
                        // Update progress position
                        progressReminder += op.Progress;
                        // Time to send progress event
                        if (session.ProgressInterval > 0L && progressReminder > session.ProgressInterval && session.HasObservers)
                        {
                            progressReminder %= session.ProgressInterval;
                            session.DispatchEvent(new OperationProgressEvent(this, Progress, TotalLength));
                        }
                    }
                }
                catch (Exception e) when(session.Policy.HasFlag(OperationPolicy.BatchContinueOnError))
                {
                    errors.Add(e);
                }
            }
            // Throw captured exceptions
            if (errors.Count > 0)
            {
                throw new AggregateException(errors.ToArray());
            }
        }