/// <summary> /// 實際的 Schedule Job 執行序工作的方法 WorkThreadFunction. /// <param name="JobMethod">Job MethodInfo</param> /// <param name="TargetJobIns">要呼叫的主 Job 物件的執行個體</param> /// <param name="job">JobData</param> /// <param name="IsReTry">目前是否為 ReTry 的呼叫</param> /// <param name="writeLogAttr"></param> /// <param name="writeExAttr"></param> /// <param name="errorLevelAttr"></param> /// </summary> private Thread_Exec_Reault WorkerThreadFunction( MethodInfo JobMethod, object TargetJobIns, JobData job, bool IsReTry, LogAttributeData <WriteLogAttribute> writeLogAttr, LogAttributeData <WriteExceptionLogAttribute> writeExAttr, LogAttributeData <ErrorLevelAttribute> errorLevelAttr, Logger loggerInner, Logger loggerInnerErr) { Thread_Exec_Reault result = Thread_Exec_Reault.SUCCESS; #region NLog 相關物件 //Logger loggerInner = NLogHelper.GetFileLogConfig(LogLevel.Info); //Logger loggerInnerErr = NLogHelper.GetErrorFileLogConfig(LogLevel.Error); #endregion try { ////紀錄 LOG 工作開始 //NLogHelper.LoggerWriter(loggerInner, job.JobName, job.DLLName, "[ScheduleJob]", "[工作開始]", ""); //執行工作 JobMethod.Invoke(TargetJobIns, new object[] { job, writeLogAttr, writeExAttr, errorLevelAttr, loggerInner, loggerInnerErr }); //執行成功後,紀錄 [執行紀錄] 表示執行過此 Job,若發生錯則只在下方的 catch 中記錄 錯誤資訊. NLogHelper.LoggerWriter(loggerInner, job.JobName, job.DLLName, string.Format("[{0}]", job.JobName)); } catch (Exception ex) { result = Thread_Exec_Reault.FAIL; //如果是被呼叫的 DLL內發生錯誤,就將錯誤 LOG 起來 //throw ex; //當然,先決條件就是,DLL 必須存在,否則 TargetJobIns 會是 null. if (JobMethod != null && TargetJobIns != null) { string ErrMessage = ex.InnerException != null ? ex.InnerException.Message : ex.Message; if (IsReTry) { NLogHelper.LoggerExWriter(loggerInnerErr, job.JobName, job.DLLName, string.Format("[{0}]", job.JobName), string.Format(" [ReTry] {0}", ErrMessage)); } else { NLogHelper.LoggerExWriter(loggerInnerErr, job.JobName, job.DLLName, string.Format("[{0}]", job.JobName), ErrMessage); } } } finally { //不管執行序內是正常執行結束、或是發生錯誤後才結束,都將執行序設定為執行序結束 _EventStopThread.Set(); } return(result); }
/// <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); } }