框架_Quartz框架+可视化+log4日志

Quartz目录

1.最简单版本Quarz Demo  (Quarz就是包含三个角色: 任务调度(Scheduler),具体任务(Job),时间策略(Trigger))

  1.1: Cron时间策略工具   https://cron.qqe2.com/

       1.2 Quarz的参数传递与获取

  1.3 Quarz的参数传递与获取-获取上一次的执行结果作为参数传递(标记特性+使用put方法)

  1.4 设置只有上一个任务完成才会执行下一次任务  5s执行一次, 但是执行的任务时长是10s,下一次任务执行就会产生问题

2:监控策略,框架提供了三个角色的各个操作接口监控调用

4.额外监控策略

5.Quarz可视化 可视化原理:定时服务单独一个进程, Web另起一个进程通过协议去监听定时服务

6.配置文件  JOB和Trigger设置可配置

7.程序集成到WindowsService最终应用

8.添加log4net日志

 

Quarz为什么分为三个角色:单一职责,(角色分拆)更加灵活装配

//更新字段:
//更新A表中的某一个字段
//更新B表中的某一个字段
//跟新C表中的某一个字段
//跟新D表中的某一个字段
//跟新E表中的某一个字段

不合适做法:没更新表的一个字段都去定义一个Job类
合适做法:定义一个job,,表名称+字段名称作为餐宿传递 一个job解决多个问题;去掉重复
//角色分开以后,就可以自由的配置时间,让一个job 在不同的时间点去执行任务(更加灵活一些)

 

 

1.最简单版本Quarz Demo

1.1.添加控制台中心,Nuget添加Quarz

using DispatcherProject.CustomJob;
using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/// <summary>
/// 调度项目
/// </summary>
namespace DispatcherProject
{
    /// <summary>
    /// 调度管理
    /// </summary>
    public class QuarZManager
    {
        /// <summary>
        /// 初始化
        /// </summary>
        public async static void Init()
        {
            #region 容器


            //1.Nuget 引入Quarz
            //2.创建一个Scheduler  任务调度容器(任务调度都是通过Scheduler来的)
            StdSchedulerFactory factory = new StdSchedulerFactory();
            //创建了一个容器
            IScheduler scheduler = await factory.GetScheduler();
            #endregion

            #region 任务
            //3.定义JOB 具体的任务定义
            IJobDetail job = JobBuilder.Create<SendMeassagerJob>().Build();
            #endregion

            #region 时间

            //4.多少时间,执行多少次
            //ITrigger trigger = TriggerBuilder.Create()
            //    .WithSimpleSchedule(build=> {
            //        build.WithIntervalInHours(3)//设置时间间隔,时分秒
            //              .WithMisfireHandlingInstructionFireNow()
            //              .WithRepeatCount(3);//设置执行次数,总共执行3次 //注释掉了就一直执行
            //        })
            //    .Build();

            ITrigger trigger = TriggerBuilder.Create()
             .WithSimpleSchedule(build => {
                 build.WithIntervalInSeconds(1)//设置时间间隔,时OR分OR秒
                       .WithMisfireHandlingInstructionFireNow()
                       .WithRepeatCount(0);//设置执行次数,总共执行N+1次 初始化的时候本身会执行一次
                })
             .Build();


        //5.把时间策略和具体job加入到容器,并设置开始
          await scheduler.ScheduleJob( job, trigger);
          await  scheduler.Start();
            #endregion

        }
    }
}
1.创建任务调度容器,2.建立JOB,3.建立Trigger
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DispatcherProject.CustomJob
{
    /// <summary>
    /// 发送信息的具体定时任务
    /// </summary>
    public class SendMeassagerJob : IJob
    {
        /// <summary>
        /// 实现Ijob必须实现的执行方法,
        /// 在这里定义要做的事情
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task Execute(IJobExecutionContext context)
        {
            return Task.Run(() =>
            {
                Console.WriteLine($"ThreadID={Thread.CurrentThread.ManagedThreadId.ToString("000")}");
                Console.WriteLine($"发送一个消息、、初始化自己本身会执行一条");
            });
        }
    }
}
具体JOB

 

 

 1.1: Cron时间策略工具   https://cron.qqe2.com/

 

 1.2 Quarz的参数传递与获取

 

 

 

定时任务 获取传递的参数

 

  1.3 Quarz的参数传递与获取-获取上一次的执行结果作为参数传递(标记特性+使用put方法)

  

 

 

 

 1.4 设置只有上一个任务完成才会执行下一次任务  5s执行一次, 但是执行的任务时长是10s,下一次任务执行就会产生问题

 

 

 

 2:监控策略,框架提供了三个角色的各个操作接口监控调用

 

 

 using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ZhaoxiFramework.DispatcherProject.CustomListener
{
    public class CustomSchedulerListener : ISchedulerListener
    {
        public async Task JobAdded(IJobDetail jobDetail, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine("CustomSchedulerListener.JobAdd");
            });
        }

        public Task JobDeleted(JobKey jobKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobInterrupted(JobKey jobKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobPaused(JobKey jobKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobResumed(JobKey jobKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobScheduled(ITrigger trigger, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobsPaused(string jobGroup, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobsResumed(string jobGroup, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobUnscheduled(TriggerKey triggerKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task SchedulerError(string msg, SchedulerException cause, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task SchedulerInStandbyMode(CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task SchedulerShutdown(CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task SchedulerShuttingdown(CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task SchedulerStarted(CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task SchedulerStarting(CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task SchedulingDataCleared(CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task TriggerFinalized(ITrigger trigger, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task TriggerPaused(TriggerKey triggerKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task TriggerResumed(TriggerKey triggerKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task TriggersPaused(string triggerGroup, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task TriggersResumed(string triggerGroup, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }
    }
}
View CodeCustomISchedulerListener
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ZhaoxiFramework.DispatcherProject.CustomListener
{
    public class CustomJobListener : IJobListener
    {
        public string Name => "CustomJobListener";

        public async Task JobExecutionVetoed(IJobExecutionContext context, CancellationToken cancellationToken = default)
        {
            await Task.Run(() => {
                Console.WriteLine("CustomJobListener.JobExecutionVetoed");
            });
        }

        public async Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default)
        {
            await Task.Run(() => {
                Console.WriteLine("CustomJobListener.JobToBeExecuted");
            });
        }

        public async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default)
        {
            await Task.Run(()=> {
                Console.WriteLine("CustomJobListener.JobWasExecuted");
            });
        }
    }
}
CustomJobListener
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ZhaoxiFramework.DispatcherProject.CustomListener
{
    public class CustomTriggerListener : ITriggerListener
    {
        public string Name => "CustomTriggerListener";

        /// <summary>
        /// 完成时执行
        /// </summary>
        /// <param name="trigger"></param>
        /// <param name="context"></param>
        /// <param name="triggerInstructionCode"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task TriggerComplete(ITrigger trigger, IJobExecutionContext context, SchedulerInstruction triggerInstructionCode, CancellationToken cancellationToken = default)
        {
            await Task.Run(()=> {
                Console.WriteLine("CustomTriggerListener.TriggerComplete");
            });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="trigger"></param>
        /// <param name="context"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task TriggerFired(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($"CustomTriggerListener TriggerFired {trigger.Description}");
            });
        }

        public async Task TriggerMisfired(ITrigger trigger, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($"CustomTriggerListener TriggerMisfired {trigger.Description}");
            });
        }


        /// <summary>
        /// 要不要放弃job
        /// </summary>
        /// <param name="trigger"></param>
        /// <param name="context"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> VetoJobExecution(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($"CustomTriggerListener VetoJobExecution {trigger.Description}");
            });
            return false;
        }
    }
}
CustomTriggerListener

 

 

 

3.具体执行策略中心

using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DispatcherProject.QuartzNet.CustomJob
{

    [PersistJobDataAfterExecution] //锚点1:设置这个后  可以在执行后可以保留执行结果
    [DisallowConcurrentExecution] //设置这个后 让定时执行的任务变成串行,必须等待前面任务执行完成才会继续执行下一个任务,就像设置每5秒执行一次任务,但是前面任务没执行完成,后面任务又开始了就会存在问题
    public class SendMessage : IJob
    {

        //private static object obj = new object(); //定义一个静态变量也可以实现 执行后可以保留执行结果

        public SendMessage()
        {
            Console.WriteLine("SendMessage 被构造");
        }

        public async Task Execute(IJobExecutionContext context) //context 很强大  他会包含我们想要的切
        {
            await Task.Run(() =>
            {

                Thread.Sleep(5000);

                #region  sendJob 
                    //发消息:给谁发,需要传递参数;
                     Console.WriteLine();
                    Console.WriteLine("**********************************************");
                    JobDataMap jobDetailMap = context.JobDetail.JobDataMap;

                    Console.WriteLine($"{jobDetailMap.Get("字符串1")}{DateTime.Now}");
                    Console.WriteLine($"{jobDetailMap.Get("字符串2")}{DateTime.Now}");
                    Console.WriteLine($"{jobDetailMap.Get("字符串3")}{DateTime.Now}");
                    Console.WriteLine($"{jobDetailMap.Get("字符串4")}{DateTime.Now}");
                    Console.WriteLine($"{jobDetailMap.Get("Year")}");
                    jobDetailMap.Put("Year", jobDetailMap.GetInt("Year") + 1);

                    JobDataMap triggerMap = context.Trigger.JobDataMap;
                    Console.WriteLine();

                #endregion

                #region trigger 

                    Console.WriteLine($"{triggerMap.Get("时间策略的字符串1")}{DateTime.Now}");
                    Console.WriteLine($"{triggerMap.Get("时间策略的字符串2")}{DateTime.Now}");
                    Console.WriteLine($"{triggerMap.Get("时间策略的字符串3")}{DateTime.Now}");
                    Console.WriteLine($"{triggerMap.Get("时间策略的字符串4")}{DateTime.Now}");

                    //锚点1 获取执行的结果
                    var getYear = triggerMap.Get("Year");
                    Console.WriteLine($"{triggerMap.Get("Year")}");

                    Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
                    Console.WriteLine(context.MergedJobDataMap.Get("Year"));
                    Console.WriteLine("**********************************************");
                    Console.WriteLine();

                #endregion


            });
        }
    }
}
View Code

 

 

4.额外监控策略

  1.自定义作业监听器 监控工作任务

using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DispatcherProject.QuartzNet.CustomListener
{
    /// <summary>
    /// 自定义作业监听器,需要实行接口IJobListener
    /// </summary>
    public class CustomJobListener : IJobListener
    {
        public string Name => "CustomJobListener";

        public async Task JobExecutionVetoed(IJobExecutionContext context, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                //便于我们自己添加自己的业务逻辑
                Console.WriteLine($"{DateTime.Now} this is JobExecutionVetoed");
            });
        }
         
        public async Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($"{DateTime.Now} this is JobToBeExecuted");
            });
        }

        public async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($"{DateTime.Now} this is JobWasExecuted");
            });
        }
    }
}
View Code

  2.自定义调度程序监听器 监控调度程序

using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DispatcherProject.QuartzNet.CustomListener
{
    /// <summary>
    /// 自定义调度程序侦听器
    /// </summary>
    public class CustomSchedulerListener : ISchedulerListener
    {
        public async Task JobAdded(IJobDetail jobDetail, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($"{jobDetail.Description} 被加入到Scheduler");
            });
        }

        public async Task JobDeleted(JobKey jobKey, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($"{jobKey} 被删除 ");
            });
        }

        public Task JobInterrupted(JobKey jobKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobPaused(JobKey jobKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobResumed(JobKey jobKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public async Task JobScheduled(ITrigger trigger, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine("this is JobScheduled");
            });
        }

        public Task JobsPaused(string jobGroup, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobsResumed(string jobGroup, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobUnscheduled(TriggerKey triggerKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task SchedulerError(string msg, SchedulerException cause, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task SchedulerInStandbyMode(CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task SchedulerShutdown(CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task SchedulerShuttingdown(CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public async Task SchedulerStarted(CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($"this is SchedulerStarted");
            });
        }

        public async Task SchedulerStarting(CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($"this is SchedulerStarting");
            });
        }

        public Task SchedulingDataCleared(CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task TriggerFinalized(ITrigger trigger, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task TriggerPaused(TriggerKey triggerKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task TriggerResumed(TriggerKey triggerKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task TriggersPaused(string triggerGroup, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task TriggersResumed(string triggerGroup, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }
    }
}
View Code

  3.自定义触发监听器 监控时间策略

using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DispatcherProject.QuartzNet.CustomListener
{
    /// <summary>
    /// 自定义触发监听器
    /// </summary>
    public class CustomTriggerListener : ITriggerListener
    {
        public string Name => "CustomTriggerListener";

        public async Task TriggerComplete(ITrigger trigger, IJobExecutionContext context, SchedulerInstruction triggerInstructionCode, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            { 
                Console.WriteLine("this is TriggerComplete");
            });
        }

        public async Task TriggerFired(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine("this is TriggerFired");
            });
        }

        public async Task TriggerMisfired(ITrigger trigger, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine("this is TriggerComplete");
            });
        }

        public async Task<bool> VetoJobExecution(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine("VetoJobExecution");
            });
            return false;  //返回false才能继续执行
        }
    }
}
View Code

 

5.Quarz可视化 可视化原理:定时服务单独一个进程, Web另起一个进程通过协议去监听定时服务

5.1:新建Web MVC程序添加Quarz+CrystalQuarz.Remote引用,注意依赖项 否则会报错

 

 

 

5.2 添加类

using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DispatcherProject
{
    public class ScheduleManager
    {
        public async static Task<IScheduler> BuildScheduler()
        {
            var properties = new NameValueCollection();
            properties["quartz.scheduler.instanceName"] = "定时作业后台监控系统";

            // 设置线程池
            properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
            properties["quartz.threadPool.threadCount"] = "5";
            properties["quartz.threadPool.threadPriority"] = "Normal";

            // 远程输出配置
            properties["quartz.scheduler.exporter.type"] = "Quartz.Simpl.RemotingSchedulerExporter, Quartz";
            properties["quartz.scheduler.exporter.port"] = "5005";
            properties["quartz.scheduler.exporter.bindName"] = "QuartzScheduler";
            properties["quartz.scheduler.exporter.channelType"] = "tcp";

            var schedulerFactory = new StdSchedulerFactory(properties);
            IScheduler _scheduler = await schedulerFactory.GetScheduler();
            return _scheduler;
        }
    }
}
ScheduleManager

5.3 设置web端 web.conig的SchedulerHost Quarz定时程序中 ScheduleManager设置的属性相同

 

 5.4 Quatz容器使用ScheduleManager

 

 

5.5访问可视化界面

web程序下面的web.config path就是可视化界面的路径

English不好可以在谷歌浏览器右键选择翻译成中文

 

 

 

 

 

 

6.配置文件 配置任务

1.设置始终复制

 

 2.设置读取配置文件

 

 

 7.程序集成到WindowsService最终应用

 

7.1因为vs项目都是寄宿在IIS上  30分钟内没有任何请求 网站就会回收 所以就不符合定时任务

 

7.2新建windos服务之后 点击这个 右键安装程序

 

 

 

 

 

 

添加之后重新生成  打开所在的文件夹找到exe文件

 

 

7.3使用cmd命令 就可以执行安装windos服务了

请注意安装失败 要用:管理员身份打开

安装
C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil C:\Users\Administrator.WIN-5SSJ2G8Q8GU\source\repos\QuarZWindosService\bin\Debug\QuarZWindosService.exe

卸载
C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil /u C:\Users\Administrator.WIN-5SSJ2G8Q8GU\source\repos\QuarZWindosService\bin\Debug\QuarZWindosService.exe


服务改名称后,需要先原样卸载,再重新编译安装,要不然卸载还蛮麻烦的

 

8.添加log4net日志记录

1:管理Nuget包 添加log4net引用

2:添加log类 

using log4net;
using log4net.Config;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace  Common
{
    public class CustomLogger
    {
        static CustomLogger()
        {
            XmlConfigurator.Configure(new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CfgFiles\\log4net.cfg.xml")));
            ILog Log = LogManager.GetLogger(typeof(CustomLogger));
            Log.Info("系统初始化Logger模块");
        }

        private ILog loger = null;
        public CustomLogger(Type type)
        {
            loger = LogManager.GetLogger(type);
        }

        /// <summary>
        /// Log4日志
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="ex"></param>
        public void Error(string msg = "出现异常", Exception ex = null)
        {
            Console.WriteLine(msg);
            loger.Error(msg, ex);
        }

        /// <summary>
        /// Log4日志
        /// </summary>
        /// <param name="msg"></param>
        public void Warn(string msg)
        {
            Console.WriteLine(msg);
            loger.Warn(msg);
        }

        /// <summary>
        /// Log4日志
        /// </summary>
        /// <param name="msg"></param>
        public void Info(string msg)
        {
            Console.WriteLine(msg);
            loger.Info(msg);
        }

        /// <summary>
        /// Log4日志
        /// </summary>
        /// <param name="msg"></param>
        public void Debug(string msg)
        {
            Console.WriteLine(msg);
            loger.Debug(msg);
        }

    }
}
logger

3.添加配置文件 记得要设置始终复制

<?xml version="1.0" encoding="utf-8"?>
<log4net>
    <!-- Define some output appenders -->
    <appender name="rollingAppender" type="log4net.Appender.RollingFileAppender">
        <file value="log\log.txt" />

        <!--追加日志内容-->
        <appendToFile value="true" />

        <!--防止多线程时不能写Log,官方说线程非安全-->
        <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />

        <!--可以为:Once|Size|Date|Composite-->
        <!--Composite为Size和Date的组合-->
        <rollingStyle value="Composite" />

        <!--当备份文件时,为文件名加的后缀-->
        <datePattern value="yyyyMMdd.TXT" />

        <!--日志最大个数,都是最新的-->
        <!--rollingStyle节点为Size时,只能有value个日志-->
        <!--rollingStyle节点为Composite时,每天有value个日志-->
        <maxSizeRollBackups value="20" />

        <!--可用的单位:KB|MB|GB-->
        <maximumFileSize value="3MB" />

        <!--置为true,当前最新日志文件名永远为file节中的名字-->
        <staticLogFileName value="true" />

        <!--输出级别在INFO和ERROR之间的日志-->
        <filter type="log4net.Filter.LevelRangeFilter">
            <param name="LevelMin" value="INFO" />
            <param name="LevelMax" value="FATAL" />
        </filter>

        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
        </layout>
    </appender>

    <!-- levels: OFF > FATAL > ERROR > WARN > INFO > DEBUG  > ALL -->
    <root>
        <priority value="ALL"/>
        <level value="ALL"/>
        <appender-ref ref="rollingAppender" />
    </root>
</log4net>
log4net.cfg.xml

4:使用日志

 

 

添加之后Log4net之后:重新生成 在卸载服务,安装服务 然后服务记得启动

 

 

 

日志和正常输出

 

posted @ 2020-06-23 11:14  12不懂3  阅读(1053)  评论(0编辑  收藏  举报
创作不易,请勿抄袭,欢迎转载!