C# · 12月 19, 2021

线程执行超时处理、并发线程数控制

说明:这里限制了并发执行存储过程的最大个数,但并没有对并发线程数进行控制,与文章标题略有不符,但程序稍做改动即可控制并发线程数

 

需求及解决方案:

1、定时执行存储过程,如何判断执行时间已到,并且不能重复执行?

    不能用等于号判断时间相等,这样不太可靠,我采用的办法是用大于号判断,并且执行过后在数据库中记录一下,防止重复执行

2、如何限制同时执行的存储过程的个数?

    定义了一个静态变量,通过静态变量判断

 

代码:

using System; System.Collections.Generic; System.ComponentModel; System.Configuration; System.Data; System.Data.OracleClient; System.Diagnostics; System.IO; System.ServiceProcess; System.Text; System.Threading; System.Timers; System.Xml; DBUtil; FQDService.DAL; FQDService.Models; FQDService.Utils;namespace FQDService{ /// <summary> /// FQD服务 </summary> partial class FQDService : ServiceBase { #region 变量 <summary> 执行存储过程线程数锁 </summary> public static Object lockTreadCount = new Object(); 执行存储过程超时时间 static int timeout = int.Parse(ConfigurationManager.AppSettings[“Timeout”].Trim()) * 60 * 1000; 等待执行存储过程时间间隔 int interval = 执行存储过程最大数 int maxRunProcCount = MaxRunProcCount 执行存储过程数 int runProcCount = 0; #endregion #region 构造函数 public FQDService() { InitializeComponent(); } #region 启动 protected override void OnStart(string[] args) { // TODO: 在此处添加代码以启动服务。 System.Timers.Timer timer = new System.Timers.Timer(); timer.Elapsed += System.Timers.ElapsedEventHandler(RunProc); timer.Start(); } #region 结束 void OnStop() { TODO: 在此处添加代码以执行停止服务所需的关闭操作。 } #region 执行存储过程 执行存储过程 void RunProc(object sender,ElapsedEventArgs e) { try { Random rnd = new Random(); List<RunTimeCfg> runTimeCfgList = RunTimeCfgDal.GetListAll(); foreach (RunTimeCfg runTimeCfg in runTimeCfgList) 遍历Proc { #region 判断是否到执行时间 bool run = false; if (runTimeCfg.RunType == 1) 按天执行 { 今天没有执行过并且执行时间已到 if (DateTime.Now.Day != RunTimeCfgDal.GetLastRunTime(runTimeCfg.ProcName)) { DateTime dtRunTime = DateTime.Parse(DateTime.Now.ToString(yyyy-MM-dd “) + runTimeCfg.RunTimeList[]); if (DateTime.Now >= dtRunTime) run = true; } } else 2) 按月执行foreach (string runTime in runTimeCfg.RunTimeList) { 今天是配置的日期并且今天没有执行过并且执行时间已到 int day = int.Parse(runTime.Split(‘ ‘)[if (DateTime.Now.Day != RunTimeCfgDal.GetLastRunTime(runTimeCfg.ProcName) && DateTime.Now.Day == day) { DateTime dtRunTime = DateTime.Parse(DateTime.Now.ToString(yyyy-MM-“) + runTime); ; } } } #endregion if (run) { #region 执行 RunTimeCfgDal.SaveLastRunTime(runTimeCfg.ProcName); 更新最后执行时间 bool finish = false; 存储过程是否执行完毕 Thread thread = null; thread = new Thread(new ParameterizedThreadStart(delegate( obj) { #region 等待执行存储过程 lock (lockTreadCount) { while (runProcCount >= maxRunProcCount) { Thread.Sleep(interval); } runProcCount++; } #endregion #region 执行存储过程超时处理 Thread threadTimer = obj2) { Thread.Sleep(timeout); if (finish == ) { FileLogger.WriteLog(string.Format(存储过程{0}执行超时”,runTimeCfg.ProcName)); if (thread != ) { { thread.Abort(); } catch (Exception ex) { FileLogger.WriteErrorLog(存储过程{0}终止线程出错:{1}#region 为执行存储过程准备参数 OracleParameter[] oracleParams = new OracleParameter[2]; oracleParams[0] = new OracleParameter(runType1] = cutTime0].Value = 1; oracleParams[1].Value = DateTime.Now.Date; { { #region 执行存储过程 FileLogger.WriteLog(开始执行存储过程{0}执行存储过程 OracleHelper.RunProcedure(runTimeCfg.ProcName,oracleParams); 模拟执行存储过程 Thread.Sleep(rnd.Next(100,1900));存储过程{0}执行成功= ; #endregion } (Exception ex) { #region 执行存储过程失败日志 StringBuilder sbParams = StringBuilder(); foreach (OracleParameter oracleParam oracleParams) { sbParams.Append({0}:{1},string strParams = “”if (sbParams.Length > 0) strParams = sbParams.ToString(0,sbParams.Length – ); FileLogger.WriteErrorLog(存储过程执行失败{0}({1}):{2} } } 捕获线程终止异常 } finally { runProcCount–; } })); thread.Start(); } } } (Exception ex) { FileLogger.WriteErrorLog(ex.Message); } } }}View Code