线程执行超时处理、并发线程数控制
2014-10-16 15:19
218 查看
说明:这里限制了并发执行存储过程的最大个数,但并没有对并发线程数进行控制,与文章标题略有不符,但程序稍做改动即可控制并发线程数
需求及解决方案:
1、定时执行存储过程,如何判断执行时间已到,并且不能重复执行?
不能用等于号判断时间相等,这样不太可靠,我采用的办法是用大于号判断,并且执行过后在数据库中记录一下,防止重复执行
2、如何限制同时执行的存储过程的个数?
定义了一个静态变量,通过静态变量判断
代码:
View Code
需求及解决方案:
1、定时执行存储过程,如何判断执行时间已到,并且不能重复执行?
不能用等于号判断时间相等,这样不太可靠,我采用的办法是用大于号判断,并且执行过后在数据库中记录一下,防止重复执行
2、如何限制同时执行的存储过程的个数?
定义了一个静态变量,通过静态变量判断
代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Configuration; using System.Data; using System.Data.OracleClient; using System.Diagnostics; using System.IO; using System.ServiceProcess; using System.Text; using System.Threading; using System.Timers; using System.Xml; using DBUtil; using FQDService.DAL; using FQDService.Models; using FQDService.Utils; namespace FQDService { /// <summary> /// FQD服务 /// </summary> partial class FQDService : ServiceBase { #region 变量 /// <summary> /// 执行存储过程线程数锁 /// </summary> public static Object lockTreadCount = new Object(); /// <summary> /// 执行存储过程超时时间 /// </summary> public static int timeout = int.Parse(ConfigurationManager.AppSettings["Timeout"].Trim()) * 60 * 1000; /// <summary> /// 等待执行存储过程时间间隔 /// </summary> public static int interval = 60 * 1000; /// <summary> /// 执行存储过程最大数 /// </summary> public static int maxRunProcCount = int.Parse(ConfigurationManager.AppSettings["MaxRunProcCount"].Trim()) * 60 * 1000; /// <summary> /// 执行存储过程数 /// </summary> public static int runProcCount = 0; #endregion #region 构造函数 public FQDService() { InitializeComponent(); } #endregion #region 启动 protected override void OnStart(string[] args) { // TODO: 在此处添加代码以启动服务。 System.Timers.Timer timer = new System.Timers.Timer(60 * 1000); timer.Elapsed += new System.Timers.ElapsedEventHandler(RunProc); timer.Start(); } #endregion #region 结束 protected override void OnStop() { // TODO: 在此处添加代码以执行停止服务所需的关闭操作。 } #endregion #region 执行存储过程 /// <summary> /// 执行存储过程 /// </summary> public 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[0]); if (DateTime.Now >= dtRunTime) run = true; } } else if (runTimeCfg.RunType == 2) //按月执行 { foreach (string runTime in runTimeCfg.RunTimeList) { // 今天是配置的日期并且今天没有执行过并且执行时间已到 int day = int.Parse(runTime.Split(' ')[0]); if (DateTime.Now.Day != RunTimeCfgDal.GetLastRunTime(runTimeCfg.ProcName) && DateTime.Now.Day == day) { DateTime dtRunTime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-") + runTime); if (DateTime.Now >= dtRunTime) run = true; } } } #endregion if (run) { #region 执行 RunTimeCfgDal.SaveLastRunTime(runTimeCfg.ProcName); //更新最后执行时间 bool finish = false; //存储过程是否执行完毕 Thread thread = null; thread = new Thread(new ParameterizedThreadStart(delegate(object obj) { #region 等待执行存储过程 lock (lockTreadCount) { while (runProcCount >= maxRunProcCount) { Thread.Sleep(interval); } runProcCount++; } #endregion #region 执行存储过程超时处理 Thread threadTimer = new Thread(new ParameterizedThreadStart(delegate(object obj2) { Thread.Sleep(timeout); if (finish == false) { FileLogger.WriteLog(string.Format("存储过程{0}执行超时", runTimeCfg.ProcName)); if (thread != null) { try { thread.Abort(); } catch (Exception ex) { FileLogger.WriteErrorLog(string.Format("存储过程{0}终止线程出错:{1}", runTimeCfg.ProcName, ex.Message)); } } } })); threadTimer.Start(); #endregion #region 为执行存储过程准备参数 OracleParameter[] oracleParams = new OracleParameter[2]; oracleParams[0] = new OracleParameter("runType", OracleType.Number); oracleParams[1] = new OracleParameter("cutTime", OracleType.DateTime); oracleParams[0].Value = 1; oracleParams[1].Value = DateTime.Now.Date; #endregion try { try { #region 执行存储过程 FileLogger.WriteLog(string.Format("开始执行存储过程{0}", runTimeCfg.ProcName)); //执行存储过程 OracleHelper.RunProcedure(runTimeCfg.ProcName, oracleParams); //模拟执行存储过程 //Thread.Sleep(rnd.Next(100, 1900)); FileLogger.WriteLog(string.Format("存储过程{0}执行成功", runTimeCfg.ProcName)); finish = true; #endregion } catch (Exception ex) { #region 执行存储过程失败日志 StringBuilder sbParams = new StringBuilder(); foreach (OracleParameter oracleParam in oracleParams) { sbParams.Append(string.Format("{0}:{1},", oracleParam.ParameterName, oracleParam.Value.ToString())); } string strParams = ""; if (sbParams.Length > 0) strParams = sbParams.ToString(0, sbParams.Length - 1); FileLogger.WriteErrorLog(string.Format("存储过程执行失败{0}({1}):{2}", runTimeCfg.ProcName, strParams, ex.Message)); #endregion } } catch { //捕获线程终止异常 } finally { runProcCount--; } })); thread.Start(); #endregion } } } catch (Exception ex) { FileLogger.WriteErrorLog(ex.Message); } } #endregion } }
View Code
相关文章推荐
- C#线程执行超时处理与并发线程数控制实例
- java并发编程学习:如何等待多个线程执行完成后再继续后续处理(synchronized、join、FutureTask、CyclicBarrier)
- C# 执行固定个数任务自行控制进入线程池的线程数量,多任务同时但是并发数据限定
- 多线程线程池控制一个方法的并发量 限制只有5个线程执行任务
- 控制并发线程数的Semaphore和线程之间的数据交换Exchanger
- java通过线程控制程序执行超时(新)_hanCSDN_20130816
- java并发编程学习:如何等待多个线程执行完成后再继续后续处理(synchronized、join、FutureTask、CyclicBarrier)
- Java并发学习之八——在线程中处理不受控制的异常
- C# 执行固定个数任务自行控制进入线程池的线程数量,多任务同时但是并发数据限定
- java通过线程控制程序执行超时_hanCSDN_20130815
- 线程并发执行带来的问题
- C#线程 在某一时间内,只有N个线程在并发执行,其余都在队列中的实现 收藏
- 执行脚本实现超时时间控制 ---Process
- C#线程 在某一时间内,只有N个线程在并发执行,其余都在队列中的实现
- 编程实践笔记{Java 线程 并发处理 Webservice}
- 不定时的间隔线程和线程排队执行(LumaQQ.NET异步线程处理)
- 当线程在捕捉异常,即使马上杀掉线程,捕捉到异常之后仍然执行异常处理程序
- 异常信息:CLR无法从COM 上下文0x645e18 转换为COM上下文0x645f88,这种状态已持续60秒。拥有目标上下文/单元的线程很有可能执行的是非泵式等待或者在不发送 Windows 消息的情况下处理一个运行时间非常长的操作.这种情况通常会影响到
- 多线程并发执行---------------管理线程Boss做任务分发,n个Worker线程连续执行获得的任务
- 不定时的间隔线程和线程排队执行(LumaQQ.NET异步线程处理)