/// <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); } }