zl程序教程

您现在的位置是:首页 >  后端

当前栏目

.Net自写Task进程监控程序

2023-09-27 14:29:33 时间

需求:线上运行的job,有时间可能因为数据库异常、内存不足或者是内部其他异常导致整个进程退出,是偶发事件,但是如果进程停止,业务数据没处理积压起来,会影响业务。为了能自动监控并启动这种意外停止的进程,写了一个程序监控,每分种检查一遍,然后自动处理,实际上是非常有用的。


贴代码如下:

//主要逻辑

 var runday = DateTime.Today;

 ConfigFile.Instanse.fileName = CommonFunctions.GetAbsolutePath("Kulv.YCF.KeepTaskRun.ini");//获取配置文件绝对路径

 string ExeFile = "";

 string ServiceName = "";

 var configIndex = 1;

 RunTaskAgain(() = 

 while (true)

 ExeFile = ConfigFile.Instanse["ExeFile" + configIndex];

 if (string.IsNullOrEmpty(ExeFile)) break;

 Logger.Info("………………………………………………………… ExeFile" + configIndex + " Start……………………………………………………………");//写日志到文本文件中

 ServiceName = ConfigFile.Instanse["ServiceName" + configIndex];

 var isRun = CommonFunctions.IsProgramRun(ExeFile);//判断exe是否在运行的进程中

 if (DateTime.Today != runday)

 runday = DateTime.Today;

 Logger.Info(string.Format("ExeFile:{0},ServiceName:{1}", ExeFile, ServiceName));

 if (isRun)

 Logger.Info("程序正在运行中");

 else

 Logger.Info(string.Format("程序未运行,尝试启动服务"));

 var startResult = CommonFunctions.RunCmd(string.Format("sc start \"{0}\"", ServiceName));//通过cmd命令启动服务

 var regex = new Regex("(\r\n)+");

 startResult = regex.Replace(startResult, "$1");//多个换行替换成一个

 Logger.Info("\r\n" + startResult);

 if (startResult.Contains("失败") == false)

 Logger.Info(string.Format("启动服务成功!"));

 var phonestr = ConfigFile.Instanse["CellPhone" + configIndex];

 FinanceApiInvoke.ApiDomain = ConfigFile.Instanse["MapApiAddress" + configIndex]; ;

 if (string.IsNullOrEmpty(phonestr))

 Logger.Info(string.Format("短信接收人配置" + configIndex + "为空!"));

 else if (string.IsNullOrEmpty(FinanceApiInvoke.ApiDomain))

 Logger.Info(string.Format("短信发送API配置" + configIndex + "为空!"));

 else

 DateTime dt = DataCache.GetCache DateTime ("LastSendMsgTime");//用缓存,5分钟内只发一次短信

 if ((DateTime.Now - dt).TotalMinutes = 5)

 var phones = phonestr.Split(new char[] { , }, StringSplitOptions.RemoveEmptyEntries);

 List SMSForSendIModel msgList = new List SMSForSendIModel 

 foreach (var phone in phones)

 msgList.Add(new SMSForSendIModel()

 CompanyId = CompanyEnum.YaoChufa,

 Phone = phone,

 SendBy = "KeepTaskRun",

 UserId = 0,

 TemplateCode = "NOTICE-COMMON0",

 UserType = UserType.SystemUser,

 Content = string.Format("库存服务YCF_STOCK_TASK处于停止状态,监控程序已在尝试启动服务,如果自动启动失败,需要人工处理!如正在发布请忽略此信息。")

 var sendRet = FinanceApiInvoke.SendSmsToWithEncryptionBatch(msgList, true);//通过api提交要发的短信给内部系统

 Logger.InfoFormat("短信返回:{0}", JsonUtility.ToJson(sendRet));

 DataCache.Set DateTime ("LastSendMsgTime", DateTime.Now, 60 * 5);

 Logger.InfoFormat("job监控发短信成功");

 Logger.Info("……………………………………………………………ExeFile" + configIndex + " End………………………………………………………………");

 configIndex++;

 catch (Exception ex)

 Logger.Info("配置" + configIndex + ",ErrorMessage:" + ExceptionMessage.GetOnlyMessage(ex));

 }, Logger, this.GetType().Name);


//配置文件-Kulv.YCF.KeepTaskRun.ini

[配置1]

ExeFile1=D:\Task\StockTask\YCF.Stock.Task.exe

ServiceName1=YCF_Stock_Task

CellPhone1=15920522222,15920522223

MapApiAddress1=

[配置2]

ExeFile2=D:\Task\StockTask\YCF.Stock.Task2.exe

ServiceName2=YCF_Stock_Task2

CellPhone2=15920522222,15920522223

MapApiAddress2=

[配置3]

ExeFile3=D:\Task\StockTask\YCF.Stock.Task3.exe

ServiceName3=YCF_Stock_Task3

CellPhone3=15920522222,15920522223

MapApiAddress3=


//判断方法:

 /// summary 

 /// 判断程序是否正在运行

 /// /summary 

 /// param name="exefile" The exefile. /param 

 /// returns /returns 

 public static bool IsProgramRun(string exefile)

 {//D:\FinancePartTask\Kulv.YCF.Task.exe

 Process[] processes = Process.GetProcesses();

 string FileName = "";

 bool ret = false;

 Process toKill = null;

 foreach (Process thisproc in processes)

 FileName = thisproc.MainModule.FileName;

 if (FileName == exefile)

 toKill = thisproc;

 break;

 catch// (Exception ex)

 //FileName = "不能访问";

 if (toKill != null)

 ret = true;

 else

 ret = false;

 catch// (Exception ex)

 ret = false;

 return ret;

 /// summary 

 /// 运行传入的cmd命令

 /// /summary 

 /// param name="cmd" cmd语句 /param 

 /// returns /returns 

 public static string RunCmd(string cmd, string cmdCurrentDir = null)

 string ret = "";

 if (!string.IsNullOrEmpty(cmdCurrentDir)) cmd = "cd /d " + cmdCurrentDir + " " + cmd;

 cmd = cmd + " exit"; //说明:不管命令是否成功均执行exit命令,否则当调用ReadToEnd()方法时,会处于假死状态

 using (var p = new Process())

 p.StartInfo.FileName = "cmd.exe";

 p.StartInfo.UseShellExecute = false; //是否使用操作系统shell启动

 p.StartInfo.RedirectStandardInput = true; //接受来自调用程序的输入信息

 p.StartInfo.RedirectStandardOutput = true; //由调用程序获取输出信息

 p.StartInfo.RedirectStandardError = true; //重定向标准错误输出

 p.StartInfo.CreateNoWindow = true; //不显示程序窗口

 p.Start(); //启动程序

 //向cmd窗口写入命令

 p.StandardInput.WriteLine(cmd);

 p.StandardInput.AutoFlush = true;

 p.WaitForExit(); //等待程序执行完退出进程

 ret = p.StandardOutput.ReadToEnd();

 p.Close();

 return ret;



这样,业务task异常退出之后,程序会自动启动服务,对task正常运行多了一层保障。

有人会问,监控程序本身也会异常退出呀,根据运行情况来看,没有异常退出过,因为程序内部与数据库等等都没交互,不会引发不明情况的异常退出,所以基本上不会异常退出。






C#.NET使用Task,await,async,异步执行控件耗时事件(event),不阻塞UI线程和不跨线程执行UI更新,以及其他方式比较 原文:C#.NET使用Task,await,async,异步执行控件耗时事件(event),不阻塞UI线程和不跨线程执行UI更新,以及其他方式比较 使用Task,await,async,异步执行事件(event),不阻塞UI线程和不跨线程执行UI更新 使用Task,await,async 的异步模式 去执行事件(event) 解决不阻塞UI线程和不夸跨线程执行UI更新报错的最佳实践,附加几种其他方式比较 由于是Winform代码和其他原因,本文章只做代码截图演示,不做界面UI展示,当然所有代码都会在截图展示。
.Net4.0 任务(Task) 任务(Task)是一个管理并行工作单元的轻量级对象。它通过使用CLR的线程池来避免启动专用线程,可以更有效率的利用线程池。System.Threading.
.NET 并行(多核)编程系列之五 Task执行和异常处理 原文:.NET 并行(多核)编程系列之五 Task执行和异常处理 .NET 并行(多核)编程系列之五 Task执行和异常处理 前言:本篇主要讲述等待task执行完成。 本篇的议题如下: 1. 等待Task执行完成 2.