框架_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 @   12不懂3  阅读(1099)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
创作不易,请勿抄袭,欢迎转载!
点击右上角即可分享
微信分享提示