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

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

 

需求及解决方案:

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

 

你可能感兴趣的:(并发线程)