C# Quartz 整理

因项目需要,在C#中使用了定时程序。自然就使用了Quartz了

但是使用的时候,经过一段时间后,发现了两个重大问题,结果导致的是一样的,就是都导致了定时不会继续执行了。

第一个问题是,定时程序发布在IIS下,但是IIS自己本身是有回收机制的,然后如果到了晚上,没人操作后台了,那么IIS会自动回收定时程序。

这里可以通过代码层面解决,就是说让IIS一直处于被使用状态,自然就不会回收了。

具体的代码改动是:

在项目中的Global.asax文件里,增加一段

protected void Application_End(object sender, EventArgs e)
        {
            // 在应用程序关闭时运行的代码   
            //解决应用池回收问题   
            System.Threading.Thread.Sleep(5000);
            string strUrl = ProjectPara.ProPath;
            System.Net.HttpWebRequest _HttpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(strUrl);
            System.Net.HttpWebResponse _HttpWebResponse = (System.Net.HttpWebResponse)_HttpWebRequest.GetResponse();
            System.IO.Stream _Stream = _HttpWebResponse.GetResponseStream();//得到回写的字节流   
        }

这个的方法触发的节点是应用程序关闭的时候会执行此方法,目的是通过HttpWebRequest发送一次请求,然后得到返回的字节流,这样每次应用程序关闭了,都会请求一次,就很好的阻止了IIS的回收。

还有一个问题是,定时程序执行中,如果程序中抛异常了,那么也会导致定时失效,原因是出现了异常,在代码中有处理,如果出现异常,直接停掉定时任务

public virtual void Execute(IJobExecutionContext context)
        {
            ValidationErrors validationErrors = new ValidationErrors();
            //取状态值
            JobDataMap dataMap = context.JobDetail.JobDataMap;
            string id = dataMap.GetString(ID);//任务ID
            string taskName = dataMap.GetString(TASKNAME);//任务名称
            //
            JobKey jobKey = context.JobDetail.Key;
            string jobName = jobKey.Name;//任务名称=任务名称+任务ID
            try
            {
                //开始执行业务逻辑
                Log.Write(jobName, "开始任务>>>>>>" + jobName, "成功");
                //取当前程序集
                Assembly assem = Assembly.GetExecutingAssembly();
                //创建任务对象并执行
                Object o = assem.CreateInstance(taskName, false,
                    BindingFlags.ExactBinding,
                    null, new Object[] { }, null, null);
                MethodInfo m = assem.GetType(taskName).GetMethod("RunJob");//默认调用方法
                Object ret = m.Invoke(o, new Object[] { dataMap, jobName, id, taskName });
                //更新任务状态
                TaskJob.UpdateState(ref validationErrors, jobName, 1, ret.ToString());
                //////////////////////////////////////////////////////////////////
                if (validationErrors.Count > 0)
                {
                    Log.Write(jobName, "Error", validationErrors.Error);
                }
                Log.Write(jobName, "<<<<<<<结束任务" + jobName, "成功");
            }
            catch (System.Exception e)
            {
                Log.Write(jobName, "Exception", e.Message);
                JobExecutionException e2 = new JobExecutionException(e);
                e2.UnscheduleAllTriggers = true;
                throw e2;
            }
        }

但是并不是所有情况都需要出现异常了,就停掉trigger,可以继续执行下次,所以注视掉这句即可。

这里引申一个问题,因为定时是invoke调用的,这个方法会忽略掉内部方法的catch,直接在当前invoke中捕获。

所以这里处理下即可。

原文地址:https://www.cnblogs.com/Rexcnblog/p/9340607.html