/// <summary>
        /// The program point of entry
        /// </summary>
        public void Run()
        {
            this._reportGeneratorEngineList = new List<Thread>();

            // While "controller" is required to run from the Service outside, then keep this Main thread "busy"
            while (this.RunProcess)
            {
                try
                {
                    #region Controller child thread execution setup and running

                    lock (this._reportGeneratorEngineList)
                    {
                        // If no more reports are busy generating, then smoke all temp files
                        if (this._reportGeneratorEngineList.Count == 0)
                        {
                            string[] tempFiles = Directory.GetFiles(this._Configuration.TempFileDirectory);

                            if (tempFiles != null && tempFiles.Length > 0)
                            {
                                for (int i = 0; i < tempFiles.Length; i++)
                                {
                                    try
                                    {
                                        File.Delete(tempFiles[i]);
                                    }
                                    catch
                                    {
                                    }
                                }
                            }
                        }

                        // Remove all threads from the processing thread queue, that is not executing a report at the moment
                        IList<Thread> finishedProcesses = this._reportGeneratorEngineList.Where(entity => (entity.ThreadState != System.Threading.ThreadState.Running
                            && entity.ThreadState != System.Threading.ThreadState.Unstarted
                            && entity.ThreadState != System.Threading.ThreadState.WaitSleepJoin)).ToList();

                        for (int i = 0; i < finishedProcesses.Count; i++)
                        {
                            Thread runner = finishedProcesses[i];

                            this._reportGeneratorEngineList.Remove(runner);
                            runner = null;
                        }

                        // If any ReportStatusId == 2 and the ReportGenerationQueueId is not in the list
                        // of threads that is executing the reports anymore, then 'RESET' the item, for regeneration
                        // & increase the retry count
                        using (GenerationDao generationDao = DataAccessFactory.Create<GenerationDao>())
                        {
                            List<ReportGenerationQueue> processingReportList = generationDao.FindAll<ReportGenerationQueue>(queue =>
                                queue.ReportGenerationStatus == ReportStatus.Processing).ToList();

                            if (processingReportList != null && processingReportList.Count > 0)
                            {
                                foreach (ReportGenerationQueue item in processingReportList)
                                {
                                    Thread runningApplication = this._reportGeneratorEngineList.FirstOrDefault(entity => entity.Name == item.ReportGenerationQueueId.ToString());

                                    if (runningApplication == null)
                                    {
                                        // this item in set to running in DB, but is not in current executing threads anymore
                                        // hence this might be a report that generated a fatal exception, that can be recovered & rescheduled
                                        this.ReportQueueStatusService.UpdateReportGenerationQueue(new ReportGenerationQueueStatusDto()
                                        {
                                            NumberOfRetries = item.NumberOfRetries + 1,
                                            ReportStatus = ReportStatus.Queued
                                        });
                                    }
                                }
                            }
                        }

                        // First the CanRunConcurrently = 0 (all the ALL reports)
                        while (this._reportGeneratorEngineList.Count < this._Configuration.ParallelProcessCount)
                        {
                            using (GenerationDao generationDao = DataAccessFactory.Create<GenerationDao>())
                            {
                                List<ReportGenerationQueue> scheduledReportList = generationDao
                                    .FindAll<ReportGenerationQueue>(queue =>
                                    queue.ReportGenerationStatus == ReportStatus.Queued).OrderBy(entity => entity.ReportGenerationQueueId).ToList();

                                // This will limit the requested reports in the "DEVELOPMENT" environment to only execute the
                                // current user that is running the process application
                                scheduledReportList = this.FilterQueueForUser(scheduledReportList);

                                ReportGenerationQueue queuedReport = scheduledReportList.FirstOrDefault();

                                if (queuedReport == null)
                                {
                                    break;
                                }

                                this.ReportQueueStatusService.UpdateReportGenerationQueue(new ReportGenerationQueueStatusDto()
                                {
                                    ReportGenerationQueueId = queuedReport.ReportGenerationQueueId,
                                    ReportStatus = ReportStatus.Processing
                                });

                                // Create a report generator and parameters based on report type
                                AbstractReportGenerator reportGenerator = null;
                                try
                                {
                                    reportGenerator = ReportGeneratorFactory.GetReportGenerator(queuedReport.ReportGenerationQueueId);
                                }
                                catch (Exception e)
                                {
                                    AbstractReportGenerator.UpdateQueuedReportStatus(
                                        this.ReportQueueStatusService,
                                        queuedReport.ReportGenerationQueueId,
                                        ReportStatus.Failed,
                                        string.Format("ReportGeneratorFactory.GetReportGenerator: {0}", e.Message));
                                    throw;
                                }

                                Thread hostedApp = new Thread(new ThreadStart(() =>
                                {
                                    try
                                    {
                                        reportGenerator.GenerateReport();
                                    }
                                    catch (Exception e)
                                    {
                                        AdaptableErrorHandler.AdaptableErrorHandlerInstance.HandleError("Application", "GRP.ReportQueue.Processor.AbstractReportGenerator.Generate()", e);
                                    }
                                }));

                                // Thread hostedApp = new Thread(new ThreadStart(reportGenerator.GenerateReport));
                                hostedApp.Name = queuedReport.ReportGenerationQueueId.ToString();

                                hostedApp.Start();

                                this._reportGeneratorEngineList.Add(hostedApp);
                            }
                        }

                        GC.Collect();
                    }

                    #endregion

                    System.Threading.Thread.Sleep(this.DatabaseQueuePollInterval);
                }
                catch (Exception ex)
                {
                    // This is to stop the service from emailling the same message 1 million times
                    // The error will only be logged if it does not exist yet or if the same error is older than 12 hour
                    ErrorItem item = this._ErrorList.FirstOrDefault(entity => entity.ExceptionMessage == ex.ToString());
                    bool addItem = false;

                    if (item != null)
                    {
                        TimeSpan ts = DateTime.Now - item.ErrorDate;

                        if (ts.Hours > 12)
                        {
                            item.ErrorDate = DateTime.Now;
                            addItem = true;
                        }
                    }
                    else
                    {
                        addItem = true;
                    }

                    if (addItem)
                    {
                        ErrorItem newItem = new ErrorItem();
                        newItem.ErrorDate = DateTime.Now;
                        newItem.ExceptionMessage = ex.ToString();

                        this._ErrorList.Add(newItem);

                        AdaptableErrorHandler.AdaptableErrorHandlerInstance.HandleError("Application", "GRP.ReportGenerationController", ex);
                    }
                }
            }

            // Wait for 5 seconds and then Abort all client threads, to allow "SAFE" stop of service process
            System.Threading.Thread.Sleep(5000);

            // Clean up all the locally created thread and confirm each have completed or is requested to aborted
            try
            {
                if (this._reportGeneratorEngineList != null)
                {
                    for (int i = 0; i < this._reportGeneratorEngineList.Count; i++)
                    {
                        this._reportGeneratorEngineList[i] = null;
                        System.Threading.Thread.Sleep(100);
                    }
                }
            }
            catch (ApplicationException ex)
            {
                AdaptableErrorHandler.AdaptableErrorHandlerInstance.HandleError("Application", "GRP.ReportGenerationController", ex);
            }
        }
        /// <summary>
        /// Handles the exception.
        /// </summary>
        /// <param name="ex">The ex.</param>
        private void HandleException(Exception ex)
        {
            // This is to stop the service from emailling the same message 1 million times
            // The error will only be logged if it does not exist yet or if the same error is older than 12 hour
            ErrorItem item = this._ErrorList.FirstOrDefault(entity => entity.ExceptionMessage == ex.ToString());
            bool addItem = false;

            if (item != null)
            {
                TimeSpan ts = DateTime.Now - item.ErrorDate;

                if (ts.Hours > 12)
                {
                    item.ErrorDate = DateTime.Now;
                    addItem = true;
                }
            }
            else
            {
                addItem = true;
            }

            if (addItem)
            {
                ErrorItem newItem = new ErrorItem();
                newItem.ErrorDate = DateTime.Now;
                newItem.ExceptionMessage = ex.ToString();

                this._ErrorList.Add(newItem);

                AdaptableErrorHandler.AdaptableErrorHandlerInstance.HandleError("Application", "GRP.ReportGenerationController", ex);
            }
        }