示例#1
0
        /// <summary>
        /// Schedule Job 主要執行序 (Main Thread).
        /// </summary>
        /// <param name="state"></param>
        protected virtual void ServiceWorkerThread(object state)
        {
            while (!this.stopping)
            {
                if (_doExpiredJob)
                {
                    if (!_isDoExpiredJob)
                    {
                        _isDoExpiredJobCurrent = true;

                        JobData jobByNonExec = RunningJobs.GetCurrentRunningJobByNonExec(); //取得上一次未執行的排程工作
                        if (jobByNonExec != null)
                        {
                            WorkerThread workerNonExec = new WorkerThread();
                            RunningTable.SetJobStatus(jobByNonExec.JobId, JobStatus.Starting);
                            workerNonExec.StartNewScheduleJob(jobByNonExec);
                        }
                        else
                        {
                            _isDoExpiredJob        = true;
                            _isDoExpiredJobCurrent = false;
                        }
                    }
                }

                if (_isDoExpiredJobCurrent) //如果系統還在執行上次未執行工作,就先不執行當前的工作.
                {
                    continue;
                }

                //檢查 RunningJob Table 裡是否有符合目前條件,可執行的工作.
                JobData job = RunningJobs.GetCurrentRunningJob();
                if (job != null)
                {
                    //MessageBox.Show(string.Format("有一個工作 {0}", job.JobName));
                    WorkerThread worker = new WorkerThread();
                    RunningTable.SetJobStatus(job.JobId, JobStatus.Starting);
                    worker.StartNewScheduleJob(job);
                }

                //在 Main Thread 中,每五秒鐘更新一次 RunningJobStatus.
                UpdateRunningJobStatus();

                Thread.Sleep(5000);  // Simulate some lengthy operations.
            }
            //迴圈停止,解除執行序鎖定
            this.stoppedEvent.Set();
        }
        /// <summary>
        /// 使用 Thread 產生一個新的 Schedule Job 執行個體.
        /// <param name="job">Schedule Job 排程相關資料</param>
        /// </summary>
        public void StartNewScheduleJob(JobData job)
        {
            #region NLog 相關物件
            Logger logger    = NLogHelper.GetFileLogConfig(LogLevel.Info);
            Logger loggerErr = NLogHelper.GetErrorFileLogConfig(LogLevel.Error);
            #endregion

            LogAttributeData <WriteLogAttribute>          writeLogAttr   = null; //建立 傳遞 WriteLogAttribute 的容器
            LogAttributeData <WriteExceptionLogAttribute> writeExAttr    = null; //建立 傳遞 WriteExceptionLogAttribute 的容器
            LogAttributeData <ErrorLevelAttribute>        errorLevelAttr = null; //建立 傳遞 ErrorLevelAttribute 的容器

            try
            {
                var resultValue = LoadAssemblyHelper.GetExecuteJobMethod(job);
                _jobMethod         = resultValue.Item1; // Job DLL Instance of Method.
                _targetJobInstance = resultValue.Item2; // Job DLL Instance.
                writeLogAttr       = resultValue.Item3;
                writeExAttr        = resultValue.Item4;
                errorLevelAttr     = resultValue.Item5;
            }
            catch (JobDLLNotFoundException dex) {
                NLogHelper.LoggerExWriter(loggerErr, job.JobName, job.DLLName, string.Format("[{0}]", job.JobName), dex.Message);
            }
            catch (JobMethodNotFoundException mex) {
                NLogHelper.LoggerExWriter(loggerErr, job.JobName, job.DLLName, string.Format("[{0}]", job.JobName), mex.Message);
            }
            catch (IActionNotImplementException aex) {
                NLogHelper.LoggerExWriter(loggerErr, job.JobName, job.DLLName, string.Format("[{0}]", job.JobName), aex.Message);
            }
            catch (Exception ex) {
                NLogHelper.LoggerExWriter(loggerErr, job.JobName, job.DLLName, string.Format("[{0}]", job.JobName), ex.Message);
            }

            try
            {
                //設定此工作目前執中.
                RunningTable.SetJobStatus(job.JobId, JobStatus.Running);
                //重設 Thread 事件狀態.
                _EventStopThread.Reset();
                //m_EventThreadStopped.Reset();

                //產生一個新的 WorkThreadFunction 的 Thread 執行個體.
                ThreadPool.QueueUserWorkItem((state) =>
                {
                    //紀錄 LOG 工作開始
                    logger = NLogHelper.GetFileLogConfig(LogLevel.Info);
                    NLogHelper.LoggerWriter(logger, job.JobName, job.DLLName, string.Format("[{0}]", job.JobName), "[JobStart]", "[JobStart]");
                    //工作開始
                    Thread_Exec_Reault result = WorkerThreadFunction(_jobMethod, _targetJobInstance, job, false, writeLogAttr, writeExAttr, errorLevelAttr, logger, loggerErr);
                    //如果前一個 WorkerThreadFunction 的執行是失敗的,就進行 ReTry 機制
                    if (result == Thread_Exec_Reault.FAIL)
                    {
                        int ReTrySec = 5000; //若未設定 config,則預設每 5 秒鐘進行 ReTry 機制
                        if (ConfigurationManager.AppSettings["ReTrySec"] != null)
                        {
                            try
                            {
                                ReTrySec = int.Parse(ConfigurationManager.AppSettings["ReTrySec"]) * 1000;
                            }
                            catch
                            {
                                loggerErr = NLogHelper.GetErrorFileLogConfig(LogLevel.Error);
                                NLogHelper.LoggerExWriter(loggerErr, job.JobName, job.DLLName, "[ScheduleJob]", "app.config in the ReTrySec parameter setting is incorrect!");
                            }
                        }

                        if (job.ReTry > 0)
                        {
                            //Thread t = new Thread((state) => { WorkerThreadFunctionReTry(iReTry, _jobMethod, _targetJobInstance, job); });
                            //t.Start();
                            // 進行 ReTry 機制.
                            // *** 變數說明 ***
                            // iReTry:要進行 ReTry 的次數
                            // ExecCount:ReRey 的次數.
                            // ReTrySec:ReRey 的秒數.
                            int iReTry = job.ReTry;
                            Task.Factory.StartNew(() =>
                            {
                                int ExecCount = 1;
                                do
                                {
                                    Logger loggerRecord = NLogHelper.GetFileLogConfig(LogLevel.Info);
                                    NLogHelper.LoggerWriter(loggerRecord, job.JobName, job.DLLName, string.Format("[{0}]", job.JobName), "[ReTry]", string.Format("Execute repeat steps {0}.....", ExecCount));
                                    Thread_Exec_Reault ReTryResult = WorkerThreadFunction(_jobMethod, _targetJobInstance, job, true, writeLogAttr, writeExAttr, errorLevelAttr, logger, loggerErr);
                                    if (ReTryResult == Thread_Exec_Reault.SUCCESS)
                                    {
                                        break; //若執行成功,隨即跳出迴圈 與 Currenthread.
                                    }
                                    Thread.Sleep(ReTrySec);
                                    iReTry--;
                                    ExecCount++;
                                } while (iReTry > 0);
                            }
                                                  );
                        }
                    }
                }, job);
                //設定最後執行時間.
                RunningJobs.SetLastExecuteDateTime(job);
            }
            catch (Exception ex)
            {
                //logger = NLogHelper.GetErrorFileLogConfig(LogLevel.Error);
                NLogHelper.LoggerExWriter(loggerErr, job.JobName, job.DLLName, string.Format("[{0}]", job.JobName), ex.Message);
            }
            finally
            {
                //等待執行序收到結束信號
                _EventStopThread.WaitOne();
                //設定服務為閒置狀態
                RunningTable.SetJobStatus(job.JobId, JobStatus.Idle);
            }
        }