.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.
相关文章
- .NET 性能调优,检测工具
- servlet对应.net中的http上下文
- 检测到在集成的托管管道模式下不适用的ASP.NET设置的解决方法(非简单设置为【经典】模式)。 - CatcherX
- What is the role of Global.asax in ASP.NET?
- 【ASP.NET Core】EF Core - “影子属性” 深入浅出经典面试题:从浏览器中输入URL到页面加载发生了什么 - Part 1
- .NET C#生成随机颜色,可以控制亮度,生成暗色或者亮色 基于YUV模式判断颜色明亮度
- 利用 Monitor.TryEnter 来规避 .NET 线程死锁的源代码
- asp.net执行SqlServer存储过程!(详解!)
- win8以上安装.NET最快方法
- 使用HttpClient对ASP.NET Web API服务实现增删改查
- 在ASP.NET MVC4中实现同页面增删改查,无弹出框02,增删改查界面设计
- ASP.NET Core应用程序容器化、持续集成与Kubernetes集群部署(二)
- ASP.NET Core Web API下事件驱动型架构的实现(一):一个简单的实现
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(四)服务端介绍
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(二)基础类库介绍
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码
- .net framework msbuild环境搭建 (不装vs)
- asp.net mvc跨域filter
- [转]C# ADO.NET SqlDataAdapter中传递参数