コード例 #1
0
        /// <summary>
        /// see RepeatTemplate#WaitForResults
        /// </summary>
        /// <param name="state"></param>
        /// <returns></returns>
        protected override bool WaitForResults(IRepeatInternalState state)
        {
            IResultQueue <IResultHolder> queue = ((ResultQueueInternalState)state).ResultQueue;
            bool result = true;

            while (queue.IsExpecting())
            {
                // Careful that no runnables that are not going to finish ever get
                // onto the queue, else this may block forever.
                IResultHolder future;
                try
                {
                    future = queue.Take();
                }
                catch (ThreadInterruptedException)
                {
                    Thread.CurrentThread.Interrupt();
                    throw new RepeatException("InterruptedException while waiting for result.");
                }

                if (future.Error != null)
                {
                    state.GetExceptions().Add(future.Error);
                    result = false;
                }
                else
                {
                    RepeatStatus status = future.Result;
                    result = result && CanContinue(status);
                    ExecuteAfterInterceptors(future.Context, status);
                }
            }
            Assert.State(queue.IsEmpty(), "Future results queue should be empty at end of batch.");
            return(result);
        }
コード例 #2
0
        /// <summary>
        /// Use the TaskExecutor to generate a result. The
        /// internal state in this case is a queue of unfinished result holders of
        /// IResultHolder. The holder with the return value should not be
        /// on the queue when this method exits. The queue is scoped in the calling
        /// method so there is no need to synchronize access.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="callback"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        protected override RepeatStatus GetNextResult(IRepeatContext context, RepeatCallback callback,
                                                      IRepeatInternalState state)
        {
            ExecutingRunnable            runnable;
            IResultQueue <IResultHolder> queue = ((ResultQueueInternalState)state).ResultQueue;

            do
            {
                // Wrap the callback in a runnable that will add its result to the
                // queue when it is ready.
                runnable = new ExecutingRunnable(callback, context, queue);

                // Tell the runnable that it can expect a result. This could have
                // been in-lined with the constructor, but it might block, so it's
                // better to do it here, since we have the option (it's a private
                // class).
                runnable.Expect();

                //Start the task possibly concurrently / in the future.
                _taskExecutor.Execute(new Task(delegate { runnable.Run(); }));

                // Allow termination policy to update its state. This must happen
                // immediately before or after the call to the task executor.
                Update(context);

                // Keep going until we get a result that is finished, or early
                // termination...
            }while (queue.IsEmpty() && !IsComplete(context));

            IResultHolder result = queue.Take();

            if (result.Error != null)
            {
                throw result.Error;
            }
            return(result.Result);
        }
コード例 #3
0
        /// <summary>
        /// see RepeatTemplate#WaitForResults
        /// </summary>
        /// <param name="state"></param>
        /// <returns></returns>
        protected override bool WaitForResults(IRepeatInternalState state)
        {
            IResultQueue<IResultHolder> queue = ((ResultQueueInternalState)state).ResultQueue;
            bool result = true;
            while (queue.IsExpecting())
            {
                // Careful that no runnables that are not going to finish ever get
                // onto the queue, else this may block forever.                 
                IResultHolder future;
                try
                {
                    future = queue.Take();
                }
                catch (ThreadInterruptedException)
                {
                    Thread.CurrentThread.Interrupt();
                    throw new RepeatException("InterruptedException while waiting for result.");
                }

                if (future.Error != null)
                {
                    state.GetExceptions().Add(future.Error);
                    result = false;
                }
                else
                {
                    RepeatStatus status = future.Result;
                    result = result && CanContinue(status);
                    ExecuteAfterInterceptors(future.Context, status);
                }
            }
            Assert.State(queue.IsEmpty(), "Future results queue should be empty at end of batch.");
            return result;
        }
コード例 #4
0
        /// <summary>
        /// Use the TaskExecutor to generate a result. The
        /// internal state in this case is a queue of unfinished result holders of
        /// IResultHolder. The holder with the return value should not be
        /// on the queue when this method exits. The queue is scoped in the calling
        /// method so there is no need to synchronize access.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="callback"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        protected override RepeatStatus GetNextResult(IRepeatContext context, RepeatCallback callback,
            IRepeatInternalState state)
        {
            ExecutingRunnable runnable;
            IResultQueue<IResultHolder> queue = ((ResultQueueInternalState)state).ResultQueue;
            do
            {
                // Wrap the callback in a runnable that will add its result to the
                // queue when it is ready.                
                runnable = new ExecutingRunnable(callback, context, queue);

                // Tell the runnable that it can expect a result. This could have
                // been in-lined with the constructor, but it might block, so it's
                // better to do it here, since we have the option (it's a private
                // class).
                runnable.Expect();

                //Start the task possibly concurrently / in the future.
                _taskExecutor.Execute(new Task(delegate { runnable.Run(); }));

                // Allow termination policy to update its state. This must happen
                // immediately before or after the call to the task executor.
                Update(context);

                // Keep going until we get a result that is finished, or early
                // termination...                 
            }
            while (queue.IsEmpty() && !IsComplete(context));

            IResultHolder result = queue.Take();
            if (result.Error != null)
            {
                throw result.Error;
            }
            return result.Result;
        }
コード例 #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="callback"></param>
        /// <returns></returns>
        private RepeatStatus ExecuteInternal(RepeatCallback callback)
        {
            // Reset the termination policy if there is one...
            IRepeatContext context = Start();

            // Make sure if we are already marked complete before we start then no
            // processing takes place.
            bool running = !IsMarkedComplete(context);

            foreach (IRepeatListener interceptor in _listeners)
            {
                interceptor.Open(context);
                running = running && !IsMarkedComplete(context);
                if (!running)
                {
                    break;
                }
            }

            // Return value, default is to allow continued processing.
            RepeatStatus result = RepeatStatus.Continuable;

            IRepeatInternalState state = CreateInternalState(context);
            // This is the list of exceptions thrown by all active callbacks
            ICollection <System.Exception> exceptions = state.GetExceptions();
            // Keep a separate list of exceptions we handled that need to be
            // rethrown
            ICollection <System.Exception> deferred = new List <System.Exception>();

            try
            {
                while (running)
                {
                    #region WhileRunning

                    /*
                     * Run the before interceptors here, not in the task executor so
                     * that they all happen in the same thread - it's easier for
                     * tracking batch status, amongst other things.
                     */
                    foreach (IRepeatListener interceptor in _listeners)
                    {
                        interceptor.Before(context);
                        // Allow before interceptors to veto the batch by setting
                        // flag.
                        running = running && !IsMarkedComplete(context);
                    }

                    // Check that we are still running (should always be true) ...
                    if (running)
                    {
                        #region Running
                        try
                        {
                            result = GetNextResult(context, callback, state);
                            ExecuteAfterInterceptors(context, result);
                        }
                        catch (System.Exception exception)
                        {
                            DoHandle(exception, context, deferred);
                        }

                        // N.B. the order may be important here:
                        if (IsComplete(context, result) || IsMarkedComplete(context) || deferred.Any())
                        {
                            running = false;
                        }
                        #endregion
                    }
                    #endregion
                }

                result = result.And(WaitForResults(state));
                foreach (System.Exception exception in exceptions)
                {
                    DoHandle(exception, context, deferred);
                }

                // Explicitly drop any references to internal state...
                // useless ?
                state = null;
            }

            /*
             * No need for explicit catch here - if the business processing threw an
             * exception it was already handled by the helper methods. An exception
             * here is necessarily fatal.
             */
            finally
            {
                #region HandleFinally
                HandleFinally(deferred, _listeners, context);
                #endregion
            }
            return(result);
        }
コード例 #6
0
 /// <summary>
 ///  If necessary, wait for results to come back from remote or concurrent
 /// processes. By default does nothing and returns true.
 /// </summary>
 /// <param name="state"></param>
 /// <returns></returns>
 protected virtual bool WaitForResults(IRepeatInternalState state)
 {
     // no-op by default
     return(true);
 }
コード例 #7
0
 /// <summary>
 ///  Get the next completed result, possibly executing several callbacks until
 /// one finally finishes. Normally a subclass would have to override both
 /// this method and <see cref="CreateInternalState"/> because the
 /// implementation of this method would rely on the details of the internal
 /// state.
 /// </summary>
 /// <param name="context"></param>
 /// <param name="callback"></param>
 /// <param name="state"></param>
 /// <returns></returns>
 /// <exception cref="Exception">&nbsp;</exception>
 protected virtual RepeatStatus GetNextResult(IRepeatContext context, RepeatCallback callback, IRepeatInternalState state)
 {
     Update(context);
     if (Logger.IsDebugEnabled)
     {
         Logger.Debug("Repeat operation about to start at count={0}", context.GetStartedCount());
     }
     return(callback(context)); //"DoInInteration"
 }
コード例 #8
0
 /// <summary>
 ///  If necessary, wait for results to come back from remote or concurrent
 /// processes. By default does nothing and returns true.        
 /// </summary>
 /// <param name="state"></param>
 /// <returns></returns>
 protected virtual bool WaitForResults(IRepeatInternalState state)
 {
     // no-op by default
     return true;
 }
コード例 #9
0
 /// <summary>
 ///  Get the next completed result, possibly executing several callbacks until
 /// one finally finishes. Normally a subclass would have to override both
 /// this method and <see cref="CreateInternalState"/> because the
 /// implementation of this method would rely on the details of the internal
 /// state.
 /// </summary>
 /// <param name="context"></param>
 /// <param name="callback"></param>
 /// <param name="state"></param>
 /// <returns></returns>
 /// <exception cref="Exception">&nbsp;</exception>
 protected virtual RepeatStatus GetNextResult(IRepeatContext context, RepeatCallback callback, IRepeatInternalState state)
 {
     Update(context);
     if (Logger.IsDebugEnabled)
     {
         Logger.Debug("Repeat operation about to start at count={0}", context.GetStartedCount());
     }
     return callback(context); //"DoInInteration"
 }