Esempio n. 1
0
        /// <summary>
        /// Adds a task to this activation.
        /// If we're adding it to the run list and we used to be waiting, now we're runnable.
        /// </summary>
        /// <param name="task">The work item to add.</param>
        public void EnqueueTask(Task task)
        {
            lock (lockable)
            {
#if DEBUG
                if (log.IsVerbose2)
                {
                    log.Verbose2("EnqueueWorkItem {0} into {1} when TaskScheduler.Current={2}", task, SchedulingContext, TaskScheduler.Current);
                }
#endif

                if (state == WorkGroupStatus.Shutdown)
                {
                    ReportWorkGroupProblem(
                        String.Format("Enqueuing task {0} to a stopped work item group. Going to ignore and not execute it. "
                                      + "The likely reason is that the task is not being 'awaited' properly.", task),
                        ErrorCode.SchedulerNotEnqueuWorkWhenShutdown);
                    task.Ignore(); // Ignore this Task, so in case it is faulted it will not cause UnobservedException.
                    return;
                }

                long thisSequenceNumber = totalItemsEnQueued++;
                int  count = WorkItemCount;
#if TRACK_DETAILED_STATS
                if (StatisticsCollector.CollectShedulerQueuesStats)
                {
                    queueTracking.OnEnQueueRequest(1, count);
                }

                if (StatisticsCollector.CollectGlobalShedulerStats)
                {
                    SchedulerStatisticsGroup.OnWorkItemEnqueue();
                }
#endif
                workItems.Enqueue(task);
                int maxPendingItemsLimit = masterScheduler.MaxPendingItemsLimit.SoftLimitThreshold;
                if (maxPendingItemsLimit > 0 && count > maxPendingItemsLimit)
                {
                    log.Warn(ErrorCode.SchedulerTooManyPendingItems, String.Format("{0} pending work items for group {1}, exceeding the warning threshold of {2}",
                                                                                   count, Name, maxPendingItemsLimit));
                }
                if (state != WorkGroupStatus.Waiting)
                {
                    return;
                }

                state = WorkGroupStatus.Runnable;
#if DEBUG
                if (log.IsVerbose3)
                {
                    log.Verbose3("Add to RunQueue {0}, #{1}, onto {2}", task, thisSequenceNumber, SchedulingContext);
                }
#endif
                masterScheduler.RunQueue.Add(this);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Shuts down this work item group so that it will not process any additional work items, even if they
        /// have already been queued.
        /// </summary>
        internal void Stop()
        {
            lock (lockable)
            {
                if (IsActive)
                {
                    ReportWorkGroupProblem(
                        String.Format("WorkItemGroup is being stoped while still active. workItemCount = {0}."
                                      + "The likely reason is that the task is not being 'awaited' properly.", WorkItemCount),
                        ErrorCode.SchedulerWorkGroupStopping);
                }

                if (state == WorkGroupStatus.Shutdown)
                {
                    log.Warn(ErrorCode.SchedulerWorkGroupShuttingDown, "WorkItemGroup is already shutting down {0}", this.ToString());
                    return;
                }

                state = WorkGroupStatus.Shutdown;

                if (StatisticsCollector.CollectPerWorkItemStats)
                {
                    SchedulerStatisticsGroup.UnRegisterWorkItemGroup(workItemGroupStatisticsNumber);
                }

                if (StatisticsCollector.CollectGlobalShedulerStats)
                {
                    SchedulerStatisticsGroup.OnWorkItemDrop(WorkItemCount);
                }

                if (StatisticsCollector.CollectShedulerQueuesStats)
                {
                    queueTracking.OnStopExecution();
                }

                foreach (Task task in workItems)
                {
                    // Ignore all queued Tasks, so in case they are faulted they will not cause UnobservedException.
                    task.Ignore();
                }
                workItems.Clear();
            }
        }
Esempio n. 3
0
        internal WorkItemGroup(OrleansTaskScheduler sched, ISchedulingContext schedulingContext)
        {
            masterScheduler      = sched;
            SchedulingContext    = schedulingContext;
            state                = WorkGroupStatus.Waiting;
            workItems            = new Queue <Task>();
            lockable             = new Object();
            totalItemsEnQueued   = 0;
            totalItemsProcessed  = 0;
            totalQueuingDelay    = TimeSpan.Zero;
            quantumExpirations   = 0;
            TaskRunner           = new ActivationTaskScheduler(this);
            MaxPendingItemsLimit = LimitManager.GetLimit(LimitNames.LIMIT_MAX_PENDING_ITEMS);
            log = IsSystem ? TraceLogger.GetLogger("Scheduler." + Name + ".WorkItemGroup", TraceLogger.LoggerType.Runtime) : appLogger;

            if (StatisticsCollector.CollectShedulerQueuesStats)
            {
                queueTracking = new QueueTrackingStatistic("Scheduler." + SchedulingContext.Name);
                queueTracking.OnStartExecution();
            }

            if (StatisticsCollector.CollectPerWorkItemStats)
            {
                workItemGroupStatisticsNumber = SchedulerStatisticsGroup.RegisterWorkItemGroup(SchedulingContext.Name, SchedulingContext,
                                                                                               () =>
                {
                    var sb = new StringBuilder();
                    lock (lockable)
                    {
                        sb.Append("QueueLength = " + WorkItemCount);
                        sb.Append(String.Format(", State = {0}", state));
                        if (state == WorkGroupStatus.Runnable)
                        {
                            sb.Append(String.Format("; oldest item is {0} old", workItems.Count >= 0 ? workItems.Peek().ToString() : "null"));
                        }
                    }
                    return(sb.ToString());
                });
            }
        }
Esempio n. 4
0
        // This is the maximum number of waiting threads (blocked in WaitForResponse) allowed
        // per ActivationWorker. An attempt to wait when there are already too many threads waiting
        // will result in a TooManyWaitersException being thrown.
        //private static readonly int MaxWaitingThreads = 500;


        internal WorkItemGroup(OrleansTaskScheduler sched, ISchedulingContext schedulingContext, ILoggerFactory loggerFactory)
        {
            masterScheduler     = sched;
            SchedulingContext   = schedulingContext;
            state               = WorkGroupStatus.Waiting;
            workItems           = new Queue <Task>();
            lockable            = new Object();
            totalItemsEnQueued  = 0;
            totalItemsProcessed = 0;
            totalQueuingDelay   = TimeSpan.Zero;
            quantumExpirations  = 0;
            TaskRunner          = new ActivationTaskScheduler(this, loggerFactory);
            log = IsSystemPriority ? loggerFactory.CreateLogger($"{this.GetType().Namespace} {Name}.{this.GetType().Name}") : loggerFactory.CreateLogger <WorkItemGroup>();

            if (StatisticsCollector.CollectShedulerQueuesStats)
            {
                queueTracking = new QueueTrackingStatistic("Scheduler." + SchedulingContext.Name);
                queueTracking.OnStartExecution();
            }

            if (StatisticsCollector.CollectPerWorkItemStats)
            {
                workItemGroupStatisticsNumber = SchedulerStatisticsGroup.RegisterWorkItemGroup(SchedulingContext.Name, SchedulingContext,
                                                                                               () =>
                {
                    var sb = new StringBuilder();
                    lock (lockable)
                    {
                        sb.Append("QueueLength = " + WorkItemCount);
                        sb.Append(String.Format(", State = {0}", state));
                        if (state == WorkGroupStatus.Runnable)
                        {
                            sb.Append(String.Format("; oldest item is {0} old", workItems.Count >= 0 ? workItems.Peek().ToString() : "null"));
                        }
                    }
                    return(sb.ToString());
                });
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Shuts down this work item group so that it will not process any additional work items, even if they
        /// have already been queued.
        /// </summary>
        internal void Stop()
        {
            lock (lockable)
            {
                if (IsActive)
                {
                    ReportWorkGroupProblem(
                        String.Format("WorkItemGroup is being stoped while still active. workItemCount = {0}."
                                      + "The likely reason is that the task is not being 'awaited' properly.", WorkItemCount),
                        ErrorCode.SchedulerWorkGroupStopping); // Throws InvalidOperationException
                }

                if (state == WorkGroupStatus.Shutdown)
                {
                    log.Warn(ErrorCode.SchedulerWorkGroupShuttingDown, "WorkItemGroup is already shutting down {0}", this.ToString());
                    return;
                }

                state = WorkGroupStatus.Shutdown;

                if (StatisticsCollector.CollectPerWorkItemStats)
                {
                    SchedulerStatisticsGroup.UnRegisterWorkItemGroup(workItemGroupStatisticsNumber);
                }

                if (StatisticsCollector.CollectGlobalShedulerStats)
                {
                    SchedulerStatisticsGroup.OnWorkItemDrop(WorkItemCount);
                }

                if (StatisticsCollector.CollectShedulerQueuesStats)
                {
                    queueTracking.OnStopExecution();
                }

                workItems.Clear();
            }
        }
Esempio n. 6
0
        // Execute one or more turns for this activation. 
        // This method is always called in a single-threaded environment -- that is, no more than one
        // thread will be in this method at once -- but other asynch threads may still be queueing tasks, etc.
        public void Execute()
        {
            lock (lockable)
            {
                if (state == WorkGroupStatus.Shutdown)
                {
                    if (!IsActive) return;  // Don't mind if no work has been queued to this work group yet.
                    
                    ReportWorkGroupProblemWithBacktrace(
                        "Cannot execute work items in a work item group that is in a shutdown state.",
                        ErrorCode.SchedulerNotExecuteWhenShutdown); // Throws InvalidOperationException
                    return;
                }
                state = WorkGroupStatus.Running;
            }

            var thread = WorkerPoolThread.CurrentWorkerThread;

            try
            {
                // Process multiple items -- drain the applicationMessageQueue (up to max items) for this physical activation
                int count = 0;
                var stopwatch = new Stopwatch();
                stopwatch.Start();
                do 
                {
                    lock (lockable)
                    {
                        if (state == WorkGroupStatus.Shutdown)
                        {
                            if (WorkItemCount > 0)
                                log.Warn(ErrorCode.SchedulerSkipWorkStopping, "Thread {0} is exiting work loop due to Shutdown state {1} while still having {2} work items in the queue.", 
                                    thread.ToString(), this.ToString(), WorkItemCount);
                            else
                                if(log.IsVerbose) log.Verbose("Thread {0} is exiting work loop due to Shutdown state {1}. Has {2} work items in the queue.",
                                    thread.ToString(), this.ToString(), WorkItemCount);
                            
                            break;
                        }

                        // Check the cancellation token (means that the silo is stopping)
                        if (thread.CancelToken.IsCancellationRequested)
                        {
                            log.Warn(ErrorCode.SchedulerSkipWorkCancelled, "Thread {0} is exiting work loop due to cancellation token. WorkItemGroup: {1}, Have {2} work items in the queue.",
                                thread.ToString(), this.ToString(), WorkItemCount);
                            break;
                        }
                    }

                    // Get the first Work Item on the list
                    ActivationTask atask;
                    lock (lockable)
                    {
                        if (workItems.Count > 0)
                            atask = workItems.Dequeue();
                        else // If the list is empty, then we're done
                            break;
                    }

#if TRACK_DETAILED_STATS
                    if (StatisticsCollector.CollectGlobalShedulerStats)
                        SchedulerStatisticsGroup.OnWorkItemDequeue();
#endif

#if DEBUG
                    if (log.IsVerbose2) log.Verbose2("About to execute task {0} in SchedulingContext={1}", atask.Task, SchedulingContext);
#endif
                    var taskStart = stopwatch.Elapsed;

                    try
                    {
                        thread.CurrentTask = atask.Task;
#if TRACK_DETAILED_STATS
                        if (StatisticsCollector.CollectTurnsStats)
                            SchedulerStatisticsGroup.OnTurnExecutionStartsByWorkGroup(workItemGroupStatisticsNumber, thread.WorkerThreadStatisticsNumber, SchedulingContext);
#endif
                        var runner = atask.IsReactive ? RcTaskRunner : TaskRunner;
                        runner.RunTask(atask.Task);
                    }
                    catch (Exception ex)
                    {
                        log.Error(ErrorCode.SchedulerExceptionFromExecute, String.Format("Worker thread caught an exception thrown from Execute by task {0}", atask.Task), ex);
                        throw;
                    }
                    finally
                    {
#if TRACK_DETAILED_STATS
                        if (StatisticsCollector.CollectTurnsStats)
                            SchedulerStatisticsGroup.OnTurnExecutionEnd(Utils.Since(thread.CurrentStateStarted));
                        
                        if (StatisticsCollector.CollectThreadTimeTrackingStats)
                            thread.threadTracking.IncrementNumberOfProcessed();
#endif
                        totalItemsProcessed++;
                        var taskLength = stopwatch.Elapsed - taskStart;
                        if (taskLength > OrleansTaskScheduler.TurnWarningLengthThreshold)
                        {
                            SchedulerStatisticsGroup.NumLongRunningTurns.Increment();
                            log.Warn(ErrorCode.SchedulerTurnTooLong3, "Task {0} in WorkGroup {1} took elapsed time {2:g} for execution, which is longer than {3}. Running on thread {4}",
                                OrleansTaskExtentions.ToString(atask.Task), SchedulingContext.ToString(), taskLength, OrleansTaskScheduler.TurnWarningLengthThreshold, thread.ToString());
                        }
                        thread.CurrentTask = null;
                    }
                    count++;
                } 
                while (((MaxWorkItemsPerTurn <= 0) || (count <= MaxWorkItemsPerTurn)) &&
                    ((ActivationSchedulingQuantum <= TimeSpan.Zero) || (stopwatch.Elapsed < ActivationSchedulingQuantum)));
                stopwatch.Stop();
            }
            catch (Exception ex)
            {
                log.Error(ErrorCode.Runtime_Error_100032, String.Format("Worker thread {0} caught an exception thrown from IWorkItem.Execute", thread), ex);
            }
            finally
            {
                // Now we're not Running anymore. 
                // If we left work items on our run list, we're Runnable, and need to go back on the silo run queue; 
                // If our run list is empty, then we're waiting.
                lock (lockable)
                {
                    if (state != WorkGroupStatus.Shutdown)
                    {
                        if (WorkItemCount > 0)
                        {
                            state = WorkGroupStatus.Runnable;
                            masterScheduler.RunQueue.Add(this);
                        }
                        else
                        {
                            state = WorkGroupStatus.Waiting;
                        }
                    }
                }
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Shuts down this work item group so that it will not process any additional work items, even if they
        /// have already been queued.
        /// </summary>
        internal void Stop()
        {
            lock (lockable)
            {
                if (IsActive)
                {
                    ReportWorkGroupProblem(
                        String.Format("WorkItemGroup is being stoped while still active. workItemCount = {0}." 
                        + "The likely reason is that the task is not being 'awaited' properly.", WorkItemCount),
                        ErrorCode.SchedulerWorkGroupStopping);
                }

                if (state == WorkGroupStatus.Shutdown)
                {
                    log.Warn(ErrorCode.SchedulerWorkGroupShuttingDown, "WorkItemGroup is already shutting down {0}", this.ToString());
                    return;
                }

                state = WorkGroupStatus.Shutdown;

                if (StatisticsCollector.CollectPerWorkItemStats)
                    SchedulerStatisticsGroup.UnRegisterWorkItemGroup(workItemGroupStatisticsNumber);
                
                if (StatisticsCollector.CollectGlobalShedulerStats)
                    SchedulerStatisticsGroup.OnWorkItemDrop(WorkItemCount);

                if (StatisticsCollector.CollectShedulerQueuesStats)
                    queueTracking.OnStopExecution();

                foreach (ActivationTask atask in workItems)
                {
                    // Ignore all queued Tasks, so in case they are faulted they will not cause UnobservedException.
                    atask.Task.Ignore();
                }
                workItems.Clear();
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Adds a task to this activation.
        /// If we're adding it to the run list and we used to be waiting, now we're runnable.
        /// </summary>
        /// <param name="task">The work item to add.</param>
        public void EnqueueTask(ActivationTask atask)
        {
            lock (lockable)
            {
#if DEBUG
                if (log.IsVerbose2) log.Verbose2("EnqueueWorkItem {0} into {1} when TaskScheduler.Current={2}", atask.Task, SchedulingContext, TaskScheduler.Current);
#endif

                if (state == WorkGroupStatus.Shutdown)
                {
                    ReportWorkGroupProblem(
                        String.Format("Enqueuing task {0} to a stopped work item group. Going to ignore and not execute it. "
                        + "The likely reason is that the task is not being 'awaited' properly.", atask.Task),
                        ErrorCode.SchedulerNotEnqueuWorkWhenShutdown);
                    atask.Task.Ignore(); // Ignore this Task, so in case it is faulted it will not cause UnobservedException.
                    return;
                }

                long thisSequenceNumber = totalItemsEnQueued++;
                int count = WorkItemCount;
#if TRACK_DETAILED_STATS
                if (StatisticsCollector.CollectShedulerQueuesStats)
                    queueTracking.OnEnQueueRequest(1, count);
                
                if (StatisticsCollector.CollectGlobalShedulerStats)
                    SchedulerStatisticsGroup.OnWorkItemEnqueue();
#endif
                workItems.Enqueue(atask);
                int maxPendingItemsLimit = masterScheduler.MaxPendingItemsLimit.SoftLimitThreshold;
                if (maxPendingItemsLimit > 0 && count > maxPendingItemsLimit)
                {
                    log.Warn(ErrorCode.SchedulerTooManyPendingItems, String.Format("{0} pending work items for group {1}, exceeding the warning threshold of {2}",
                        count, Name, maxPendingItemsLimit));
                }
                if (state != WorkGroupStatus.Waiting) return;

                state = WorkGroupStatus.Runnable;
#if DEBUG
                if (log.IsVerbose3) log.Verbose3("Add to RunQueue {0}, #{1}, onto {2}", atask.Task, thisSequenceNumber, SchedulingContext);
#endif
                masterScheduler.RunQueue.Add(this);
            }
        }
Esempio n. 9
0
        // This is the maximum number of waiting threads (blocked in WaitForResponse) allowed
        // per ActivationWorker. An attempt to wait when there are already too many threads waiting
        // will result in a TooManyWaitersException being thrown.
        //private static readonly int MaxWaitingThreads = 500;


        internal WorkItemGroup(OrleansTaskScheduler sched, ISchedulingContext schedulingContext)
        {
            masterScheduler = sched;
            SchedulingContext = schedulingContext;
            state = WorkGroupStatus.Waiting;
            workItems = new Queue<ActivationTask>();
            lockable = new Object();
            totalItemsEnQueued = 0;
            totalItemsProcessed = 0;
            totalQueuingDelay = TimeSpan.Zero;
            quantumExpirations = 0;
            TaskRunner = new ActivationTaskScheduler(this);
            
            log = IsSystemPriority ? LogManager.GetLogger("Scheduler." + Name + ".WorkItemGroup", LoggerType.Runtime) : appLogger;
      
            if (StatisticsCollector.CollectShedulerQueuesStats)
            {
                queueTracking = new QueueTrackingStatistic("Scheduler." + SchedulingContext.Name);
                queueTracking.OnStartExecution();
            }

            if (StatisticsCollector.CollectPerWorkItemStats)
            {
                workItemGroupStatisticsNumber = SchedulerStatisticsGroup.RegisterWorkItemGroup(SchedulingContext.Name, SchedulingContext,
                    () =>
                    {
                        var sb = new StringBuilder();
                        lock (lockable)
                        {
                                    
                            sb.Append("QueueLength = " + WorkItemCount);
                            sb.Append(String.Format(", State = {0}", state));
                            if (state == WorkGroupStatus.Runnable)
                                sb.Append(String.Format("; oldest item is {0} old", workItems.Count >= 0 ? workItems.Peek().ToString() : "null"));
                        }
                        return sb.ToString();
                    });
            }
        }
Esempio n. 10
0
        // Execute one or more turns for this activation.
        // This method is always called in a single-threaded environment -- that is, no more than one
        // thread will be in this method at once -- but other asynch threads may still be queueing tasks, etc.
        public void Execute()
        {
            lock (lockable)
            {
                if (state == WorkGroupStatus.Shutdown)
                {
                    if (!IsActive)
                    {
                        return;             // Don't mind if no work has been queued to this work group yet.
                    }
                    ReportWorkGroupProblemWithBacktrace(
                        "Cannot execute work items in a work item group that is in a shutdown state.",
                        ErrorCode.SchedulerNotExecuteWhenShutdown); // Throws InvalidOperationException
                    return;
                }
                state = WorkGroupStatus.Running;
            }

            var thread = WorkerPoolThread.CurrentWorkerThread;

            try
            {
                // Process multiple items -- drain the applicationMessageQueue (up to max items) for this physical activation
                int count     = 0;
                var stopwatch = new Stopwatch();
                stopwatch.Start();
                do
                {
                    lock (lockable)
                    {
                        if (state == WorkGroupStatus.Shutdown)
                        {
                            if (WorkItemCount > 0)
                            {
                                log.Warn(ErrorCode.SchedulerSkipWorkStopping, "Thread {0} is exiting work loop due to Shutdown state {1} while still having {2} work items in the queue.",
                                         thread.ToString(), this.ToString(), WorkItemCount);
                            }
                            else
                            if (log.IsVerbose)
                            {
                                log.Verbose("Thread {0} is exiting work loop due to Shutdown state {1}. Has {2} work items in the queue.",
                                            thread.ToString(), this.ToString(), WorkItemCount);
                            }

                            break;
                        }

                        // Check the cancellation token (means that the silo is stopping)
                        if (thread.CancelToken.IsCancellationRequested)
                        {
                            log.Warn(ErrorCode.SchedulerSkipWorkCancelled, "Thread {0} is exiting work loop due to cancellation token. WorkItemGroup: {1}, Have {2} work items in the queue.",
                                     thread.ToString(), this.ToString(), WorkItemCount);
                            break;
                        }
                    }

                    // Get the first Work Item on the list
                    Task task;
                    lock (lockable)
                    {
                        if (workItems.Count > 0)
                        {
                            task = workItems.Dequeue();
                        }
                        else // If the list is empty, then we're done
                        {
                            break;
                        }
                    }

#if TRACK_DETAILED_STATS
                    if (StatisticsCollector.CollectGlobalShedulerStats)
                    {
                        SchedulerStatisticsGroup.OnWorkItemDequeue();
                    }
#endif

#if DEBUG
                    if (log.IsVerbose2)
                    {
                        log.Verbose2("About to execute task {0} in SchedulingContext={1}", task, SchedulingContext);
                    }
#endif
                    var taskStart = stopwatch.Elapsed;

                    try
                    {
                        thread.CurrentTask = task;
#if TRACK_DETAILED_STATS
                        if (StatisticsCollector.CollectTurnsStats)
                        {
                            SchedulerStatisticsGroup.OnTurnExecutionStartsByWorkGroup(workItemGroupStatisticsNumber, thread.WorkerThreadStatisticsNumber, SchedulingContext);
                        }
#endif
                        TaskRunner.RunTask(task);
                    }
                    catch (Exception ex)
                    {
                        log.Error(ErrorCode.SchedulerExceptionFromExecute, String.Format("Worker thread caught an exception thrown from Execute by task {0}", task), ex);
                        throw;
                    }
                    finally
                    {
#if TRACK_DETAILED_STATS
                        if (StatisticsCollector.CollectTurnsStats)
                        {
                            SchedulerStatisticsGroup.OnTurnExecutionEnd(Utils.Since(thread.CurrentStateStarted));
                        }

                        if (StatisticsCollector.CollectThreadTimeTrackingStats)
                        {
                            thread.threadTracking.IncrementNumberOfProcessed();
                        }
#endif
                        totalItemsProcessed++;
                        var taskLength = stopwatch.Elapsed - taskStart;
                        if (taskLength > OrleansTaskScheduler.TurnWarningLengthThreshold)
                        {
                            SchedulerStatisticsGroup.NumLongRunningTurns.Increment();
                            log.Warn(ErrorCode.SchedulerTurnTooLong3, "Task {0} in WorkGroup {1} took elapsed time {2:g} for execution, which is longer than {3}. Running on thread {4}",
                                     OrleansTaskExtentions.ToString(task), SchedulingContext.ToString(), taskLength, OrleansTaskScheduler.TurnWarningLengthThreshold, thread.ToString());
                        }
                        thread.CurrentTask = null;
                    }
                    count++;
                }while (((MaxWorkItemsPerTurn <= 0) || (count <= MaxWorkItemsPerTurn)) &&
                        ((ActivationSchedulingQuantum <= TimeSpan.Zero) || (stopwatch.Elapsed < ActivationSchedulingQuantum)));
                stopwatch.Stop();
            }
            catch (Exception ex)
            {
                log.Error(ErrorCode.Runtime_Error_100032, String.Format("Worker thread {0} caught an exception thrown from IWorkItem.Execute", thread), ex);
            }
            finally
            {
                // Now we're not Running anymore.
                // If we left work items on our run list, we're Runnable, and need to go back on the silo run queue;
                // If our run list is empty, then we're waiting.
                lock (lockable)
                {
                    if (state != WorkGroupStatus.Shutdown)
                    {
                        if (WorkItemCount > 0)
                        {
                            state = WorkGroupStatus.Runnable;
                            masterScheduler.RunQueue.Add(this);
                        }
                        else
                        {
                            state = WorkGroupStatus.Waiting;
                        }
                    }
                }
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Shuts down this work item group so that it will not process any additional work items, even if they
        /// have already been queued.
        /// </summary>
        internal void Stop()
        {
            lock (lockable)
            {
                if (IsActive)
                {
                    ReportWorkGroupProblem(
                        String.Format("WorkItemGroup is being stoped while still active. workItemCount = {0}." 
                        + "The likely reason is that the task is not being 'awaited' properly.", WorkItemCount),
                        ErrorCode.SchedulerWorkGroupStopping); // Throws InvalidOperationException
                }

                if (state == WorkGroupStatus.Shutdown)
                {
                    log.Warn(ErrorCode.SchedulerWorkGroupShuttingDown, "WorkItemGroup is already shutting down {0}", this.ToString());
                    return;
                }

                state = WorkGroupStatus.Shutdown;

                if (StatisticsCollector.CollectPerWorkItemStats)
                    SchedulerStatisticsGroup.UnRegisterWorkItemGroup(workItemGroupStatisticsNumber);
                
                if (StatisticsCollector.CollectGlobalShedulerStats)
                    SchedulerStatisticsGroup.OnWorkItemDrop(WorkItemCount);

                if (StatisticsCollector.CollectShedulerQueuesStats)
                    queueTracking.OnStopExecution();
                
                workItems.Clear();
            }
        }