コード例 #1
0
        /// <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);
        }
コード例 #2
0
        /// <summary>
        /// 傳入 Assembly 物件,從 Assembly 指定的 NameSpace & ClassName 到 Assembly 中取得並回傳 MethodInfo.
        /// </summary>
        /// <param name="ass">Assembly for Job DLL</param>
        /// <param name="Job">JobData 物件</param>
        /// <returns>Tuple 物件 (包含:MethodIfo, new Job Instance)</returns>
        public static Tuple <MethodInfo, object, LogAttributeData <WriteLogAttribute>, LogAttributeData <WriteExceptionLogAttribute>, LogAttributeData <ErrorLevelAttribute> > Common(
            Assembly ass,
            JobData Job)
        {
            object jobClassObject = null;
            LogAttributeData <WriteLogAttribute>          writeLogAttr   = new LogAttributeData <WriteLogAttribute>();
            LogAttributeData <WriteExceptionLogAttribute> writeExAttr    = new LogAttributeData <WriteExceptionLogAttribute>();
            LogAttributeData <ErrorLevelAttribute>        errorLevelAttr = new LogAttributeData <ErrorLevelAttribute>();

            MethodInfo jobMethod           = null;
            MethodInfo BeforePrepareMethod = null;
            MethodInfo PrepareDataMethod   = null;
            MethodInfo ProcessDataMethod   = null;
            MethodInfo AfterProcessMethod  = null;

            Type magicType = ass.GetType(string.Format("{0}.{1}", Job.NameSpace, Job.ClassName));

            if (magicType != null)
            {
                //判別 Load 進來的 Class 型態是不是實作 IAction 的介面,若不是,則 throw Exception.
                if (magicType.GetInterfaces().AsEnumerable <Type>().Where(c => c == typeof(IAction)).FirstOrDefault() == null)
                {
                    throw new IActionNotImplementException(string.Format("The {0} of class {1} is must be to inheritance by interface of IAtion.", Job.DLLName, Job.ClassName))
                          {
                              Datetime   = DateTime.Now,
                              MethodInfo = string.Format("DLLPath={0}, DLLName={1}, NameSpace={2}, ClassName={3}", dllPath, Job.DLLName, Job.NameSpace, Job.ClassName)
                          };
                }

                ConstructorInfo jobConstructor = magicType.GetConstructor(Type.EmptyTypes);
                jobClassObject = jobConstructor.Invoke(null);

                jobMethod           = magicType.GetMethod(JOB_METHOD_NAME);
                BeforePrepareMethod = magicType.GetMethod(BEFORE_PREPARE_METHOD_NAME, BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic);
                PrepareDataMethod   = magicType.GetMethod(PREPARE_DATA_METHOD_NAME, BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic);
                ProcessDataMethod   = magicType.GetMethod(PROCESS_DATA_METHOD_NAME, BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic);
                AfterProcessMethod  = magicType.GetMethod(AFTER_PROCESS_METHOD_NAME, BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic);

                #region 包裝 WriteLogAttribute 容器
                writeLogAttr.SetBeforePrepareMethod(BeforePrepareMethod);
                writeLogAttr.SetPrepareDataMethod(PrepareDataMethod);
                writeLogAttr.SetProcessDataMethod(ProcessDataMethod);
                writeLogAttr.SetAfterProcessMethod(AfterProcessMethod);
                #endregion

                #region 包裝 WriteLogExAttribute 容器
                writeExAttr.SetBeforePrepareMethod(BeforePrepareMethod);
                writeExAttr.SetPrepareDataMethod(PrepareDataMethod);
                writeExAttr.SetProcessDataMethod(ProcessDataMethod);
                writeExAttr.SetAfterProcessMethod(AfterProcessMethod);
                #endregion

                #region 包裝 ErrorLevelAttribute 容器
                errorLevelAttr.SetBeforePrepareMethod(BeforePrepareMethod);
                errorLevelAttr.SetPrepareDataMethod(PrepareDataMethod);
                errorLevelAttr.SetProcessDataMethod(ProcessDataMethod);
                errorLevelAttr.SetAfterProcessMethod(AfterProcessMethod);
                #endregion

                if (jobMethod == null)
                {
                    throw new JobMethodNotFoundException("Please check the method is correct!")
                          {
                              Datetime   = DateTime.Now,
                              MethodInfo = string.Format("DLLPath={0}, DLLName={1}, NameSpace={2}, ClassName={3}", dllPath, Job.DLLName, Job.NameSpace, Job.ClassName)
                          };
                }
            }
            else
            {
                throw new JobMethodNotFoundException("Please check the namespace or class name is correct!")
                      {
                          Datetime   = DateTime.Now,
                          MethodInfo = string.Format("DLLPath={0}, DLLName={1}, NameSpace={2}, ClassName={3}", dllPath, Job.DLLName, Job.NameSpace, Job.ClassName)
                      };
            }

            return(Tuple.Create(jobMethod, jobClassObject, writeLogAttr, writeExAttr, errorLevelAttr));
        }
コード例 #3
0
        /// <summary>
        /// 傳入 JobData 物件,從 JobData 指定的 NameSpace & ClassName 到 Assembly 中取得並回傳 MethodInfo.
        /// </summary>
        /// <param name="Job">JobData 物件</param>
        public static Tuple <MethodInfo, object, LogAttributeData <WriteLogAttribute>, LogAttributeData <WriteExceptionLogAttribute>, LogAttributeData <ErrorLevelAttribute> > GetExecuteJobMethod(JobData Job)
        {
            MethodInfo result         = null;
            object     jobClassObject = null;
            LogAttributeData <WriteLogAttribute>          writeLogAttr   = new LogAttributeData <WriteLogAttribute>();
            LogAttributeData <WriteExceptionLogAttribute> writeExAttr    = new LogAttributeData <WriteExceptionLogAttribute>();
            LogAttributeData <ErrorLevelAttribute>        errorLevelAttr = new LogAttributeData <ErrorLevelAttribute>();

            string appPath = string.Empty;

            string nameSapce = string.Empty;

            try
            {
                Assembly ExecuteAssembly = Assembly.GetExecutingAssembly();
                appPath = Path.GetDirectoryName(ExecuteAssembly.Location);

                dllPath = string.Format("{0}.dll", Job.DLLName);

                // 判斷上傳的實體路徑下是否有此文件,沒有提示錯誤信息
                if (!System.IO.File.Exists(Path.Combine(appPath, dllPath)))
                {
                    throw new JobDLLNotFoundException(string.Format("The {0} DLL is not exist!", dllPath))
                          {
                              Datetime   = DateTime.Now,
                              MethodInfo = string.Format("DLLPath={0}, DLLName={1}, NameSpace={2}, ClassName={3}", dllPath, Job.DLLName, Job.NameSpace, Job.ClassName)
                          };
                }
                else
                {
                    //要讀取的 DLL 路徑.
                    string   assPath       = Path.Combine(appPath, dllPath);
                    string   dllConfigPath = string.Format("{0}.config", assPath);
                    Assembly ass           = null;

                    //先判斷是否有這個 DLL 的 dll.config
                    if (File.Exists(dllConfigPath))
                    {
                        var resultValue = GetCustomConfig(assPath, dllConfigPath, "connectionStrings");
                        ass = resultValue.Item1;
                    }
                    else
                    {
                        //載入指定路徑中的 Assembly.
                        ass = Assembly.LoadFile(assPath);
                    }

                    if (ass != null)
                    {
                        Type magicType   = ass.GetType(string.Format(".", Job.NameSpace, Job.ClassName));
                        var  resultValue = Common(ass, Job);
                        result         = resultValue.Item1;
                        jobClassObject = resultValue.Item2;
                        writeLogAttr   = resultValue.Item3;
                        writeExAttr    = resultValue.Item4;
                        errorLevelAttr = resultValue.Item5;
                    }
                    else
                    {
                        throw new JobDLLNotFoundException(string.Format("The {0} DLL is not exist!", dllPath))
                              {
                                  Datetime   = DateTime.Now,
                                  MethodInfo = string.Format("DLLPath={0}, DLLName={1}, NameSpace={2}, ClassName={3}", dllPath, Job.DLLName, Job.NameSpace, Job.ClassName)
                              };
                    }
                }
            }
            catch (Exception ex)
            {
                throw new JobDLLNotFoundException(ex.Message)
                      {
                          Datetime   = DateTime.Now,
                          MethodInfo = string.Format("DLLPath={0}, DLLName={1}, NameSpace={2}, ClassName={3}", dllPath, Job.DLLName, Job.NameSpace, Job.ClassName)
                      };
            }

            return(Tuple.Create(result, jobClassObject, writeLogAttr, writeExAttr, errorLevelAttr));
        }
コード例 #4
0
        /// <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);
            }
        }
コード例 #5
0
        //protected static Logger LOG = NLog.LogManager.GetCurrentClassLogger();
        /// <summary>
        /// 主要執行的 Method 入口
        /// <param name="job">目前執行的 Job 相關資料.</param>
        /// <param name="writeLogAttr">WriteLog 的設定相關資料</param>
        /// <param name="writeExAttr">WriteExLog 的設定相關資料</param>
        /// </summary>
        public virtual void DoJob(
            JobData job,
            LogAttributeData <WriteLogAttribute> writeLogAttr,
            LogAttributeData <WriteExceptionLogAttribute> writeExAttr,
            LogAttributeData <ErrorLevelAttribute> errorLevelAttr,
            Logger loggerInner,
            Logger loggerInnerErr)
        {
            #region NLog 相關物件
            //Logger loggerInner = NLogHelper.GetFileLogConfig(LogLevel.Info);
            //Logger loggerInnerErr = NLogHelper.GetErrorFileLogConfig(LogLevel.Error);
            #endregion

            WriteLogAttribute          LogAttr      = null;
            WriteExceptionLogAttribute LogExAttr    = null;
            ErrorLevelAttribute        ErrLevelAttr = null;

            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Reset(); //碼表歸零
            sw.Start(); //碼表開始計時

            //loggerInner.Info("[DoJob] Start");

            try
            {
                LogAttr = writeLogAttr.GetBeforePrepareAttr();          //取得當前的 BeforPrepare 方法是否有設定 WriteLogAttribute.
                if (LogAttr != null)
                {
                    WriteInfo(LogAttr, job, "[BeforePrepare] Start...");
                }

                BeforePrepare();
                if (LogAttr != null)
                {
                    loggerInner.Info(string.Format("[{0}].{1}.{2}  Completed... total {3}", job.JobName, "[DotJob]", "[BeforePrepare]", sw.Elapsed.TotalMilliseconds.ToString()));
                }
            }
            catch (Exception ex)
            {
                ErrLevelAttr = errorLevelAttr.GetBeforePrepareAttr();   //取得當前的 BeforPrepare 方法是否有設定 ErrorLevelAttribute.
                LogExAttr    = writeExAttr.GetBeforePrepareAttr();      //取得當前的 BeforPrepare 方法是否有設定 WriteExceptionLogAttribute.
                if (LogExAttr != null)
                {
                    WriteExLog(LogExAttr, job, "[BeforePrepare]", ex, ErrLevelAttr);
                }

                throw ex;
            }

            try
            {
                LogAttr = writeLogAttr.GetPrepareDataMethodAttr();
                if (LogAttr != null)
                {
                    WriteInfo(LogAttr, job, "[PrepareData] Start...");
                }

                PrepareData();
                if (LogAttr != null)
                {
                    loggerInner.Info(string.Format("[{0}].{1}.{2}  Completed... total {3}", job.JobName, "[DotJob]", "[PrepareData]", sw.Elapsed.TotalMilliseconds.ToString()));
                }
            }
            catch (Exception ex)
            {
                ErrLevelAttr = errorLevelAttr.GetPrepareDataMethodAttr(); //取得當前的 PrepareData 方法是否有設定 ErrorLevelAttribute.
                LogExAttr    = writeExAttr.GetPrepareDataMethodAttr();    //取得當前的 PrepareData 方法是否有設定 WriteExceptionLogAttribute.
                if (LogExAttr != null)
                {
                    WriteExLog(LogExAttr, job, "[PrepareData]", ex, ErrLevelAttr);
                }

                throw ex;
            }

            try
            {
                LogAttr = writeLogAttr.GetProcessDataMethodAttr();
                if (LogAttr != null)
                {
                    WriteInfo(LogAttr, job, "[ProcessData] Start...");
                }

                ProcessData();
                if (LogAttr != null)
                {
                    loggerInner.Info(string.Format("[{0}].{1}.{2}  Completed... total {3}", job.JobName, "[DotJob]", "[ProcessData]", sw.Elapsed.TotalMilliseconds.ToString()));
                }
            }
            catch (Exception ex)
            {
                ErrLevelAttr = errorLevelAttr.GetProcessDataMethodAttr(); //取得當前的 ProcessData 方法是否有設定 ErrorLevelAttribute.
                LogExAttr    = writeExAttr.GetProcessDataMethodAttr();    //取得當前的 ProcessData 方法是否有設定 WriteExceptionLogAttribute.
                if (LogExAttr != null)
                {
                    WriteExLog(LogExAttr, job, "[ProcessData]", ex, ErrLevelAttr);
                }

                throw ex;
            }

            try
            {
                LogAttr = writeLogAttr.GetAfterProcessMethodAttr();
                if (LogAttr != null)
                {
                    WriteInfo(LogAttr, job, "[AfterProcess] Start...");
                }

                AfterProcess();
                if (LogAttr != null)
                {
                    loggerInner.Info(string.Format("[{0}].{1}.{2}  End... total {3}", job.JobName, "[DotJob]", "[AfterProcess]", sw.Elapsed.TotalMilliseconds.ToString()));
                }
            }
            catch (Exception ex)
            {
                ErrLevelAttr = errorLevelAttr.GetAfterProcessMethodAttr(); //取得當前的 AfterProcess 方法是否有設定 ErrorLevelAttribute.
                LogExAttr    = writeExAttr.GetAfterProcessMethodAttr();    //取得當前的 AfterProcess 方法是否有設定 WriteExceptionLogAttribute.
                if (LogExAttr != null)
                {
                    WriteExLog(LogExAttr, job, "[AfterProcess]", ex, ErrLevelAttr);
                }

                throw ex;
            }

            sw.Stop();//碼錶停止
        }