Host服务

这也是看网上的例子自己跟着配置做的一个小demo,这里记录一下。

一、创建一个空的控制台应用程序

二、安装所需dll 

  1.Quartz 
    Install-Package Quartz -Version 2.3.3
  2.Owin
    Install-Package Owin -Version 1.0.0(这个暂时装上)
  3.TopShelf
    Install-Package TopShelf -Version 3.3.1
  4.log4net
    Install-Package log4net -Version 2.0.8
  5.TopShelf.log4net
    Install-Package Topshelf.Log4Net -Version 3.3.1

 这里我把版本都标记出来是因为NuGet安装的时候有可能最新的版本会不兼容的问题,如果出现请降版本安装。

三、手动创建

  1.log4net.config

  

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>

  <log4net>
    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <!--日志路径-->
      <param name= "File" value= "Log"/>
      <!--是否是向文件中追加日志-->
      <param name= "AppendToFile" value= "true"/>
      <!--log保留天数-->
      <param name= "MaxSizeRollBackups" value= "10"/>
      <!--日志文件名是否是固定不变的-->
      <param name= "StaticLogFileName" value= "false"/>
      <!--日志文件名格式为:2008-08-31.log-->
      <param name= "DatePattern" value= "yyyy-MM-dd&quot;.read.log&quot;"/>
      <!--日志根据日期滚动-->
      <param name= "RollingStyle" value= "Date"/>
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%date{HH:mm:ss,fff} %-5p-%m%n" />
      </layout>
    </appender>

    <!-- 控制台前台显示日志 -->
    <appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
      <mapping>
        <level value="ERROR" />
        <foreColor value="Red, HighIntensity" />
      </mapping>
      <mapping>
        <level value="Info" />
        <foreColor value="Green" />
      </mapping>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%n%date{HH:mm:ss,fff} [%-5level] %m" />
      </layout>

      <filter type="log4net.Filter.LevelRangeFilter">
        <param name="LevelMin" value="Info" />
        <param name="LevelMax" value="Fatal" />
      </filter>
    </appender>

    <root>
      <!--(高) OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL (低) -->
      <level value="all" />
      <appender-ref ref="ColoredConsoleAppender"/>
      <appender-ref ref="RollingLogFileAppender"/>
    </root>

  </log4net>
</configuration>
View Code

  2.quartz.config

# You can configure your scheduler in either <quartz> configuration section
# or in quartz properties file
# Configuration section has precedence

quartz.scheduler.instanceName = QuartzTest

# configure thread pool info
quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz
quartz.threadPool.threadCount = 10
quartz.threadPool.threadPriority = Normal

# job initialization plugin handles our xml reading, without it defaults are used
quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz
quartz.plugin.xml.fileNames = ~/quartz_jobs.xml

# export this server to remoting context
#quartz.scheduler.exporter.type = Quartz.Simpl.RemotingSchedulerExporter, Quartz
#quartz.scheduler.exporter.port = 560
#quartz.scheduler.exporter.bindName = QuartzScheduler
#quartz.scheduler.exporter.channelType = tcp
#quartz.scheduler.exporter.channelName = httpQuartz
View Code

  3.quartz_jobs.xml

<?xml version="1.0" encoding="utf-8" ?>
<!-- This file contains job definitions in schema version 2.0 format -->

<job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">

  <processing-directives>
    <overwrite-existing-data>true</overwrite-existing-data>
  </processing-directives>

  <schedule>

    <!--TestJob测试 任务配置 -->
    <job>
      <name>TestJob</name>
      <group>Test</group>
      <description>TestJob测试</description>
      <job-type>HostProject.QuartzJobs.TestJob,HostProject</job-type>
      <durable>true</durable>
      <recover>false</recover>
    </job>
    <trigger>
      <cron>
        <name>TestJobTrigger</name>
        <group>Test</group>
        <job-name>TestJob</job-name>
        <job-group>Test</job-group>
        <!-- 从start-time起,每5s执行一次IJob.Execute -->
        <start-time>2012-01-22T00:00:00+08:00</start-time>
        <cron-expression>0/5 * * * * ?</cron-expression>
      </cron>
    </trigger>

  </schedule>
</job-scheduling-data>
View Code

四、创建 ServiceRunner.cs

 public class ServiceRunner : ServiceControl, ServiceSuspend
    {
        private readonly IScheduler _IScheduler;
        public ServiceRunner()
        {
            _IScheduler = StdSchedulerFactory.GetDefaultScheduler();
        }
        public bool Start(HostControl hostControl)
        {
            _IScheduler.Start();
            return true;
        }

        public bool Stop(HostControl hostControl)
        {
            _IScheduler.Shutdown();
            return true;
        }

        public bool Continue(HostControl hostControl)
        {
            _IScheduler.ResumeAll();
            return true;
        }

        public bool Pause(HostControl hostControl)
        {
            _IScheduler.PauseAll();
            return true;
        }
    }
View Code

五、TestJob

  public sealed class TestJob:IJob
    {
        public void Execute(IJobExecutionContext context)
        {
            CommonHelper.AppLogger.InfoFormat("TestJob测试");
            try
            {

                //模拟调用存储过程,更新商品库存

                string connStr = "Data Source=.;Initial Catalog=test;User Id=sa;Password=p@ss!123;";

                using (SqlConnection conn = new SqlConnection(connStr))
                {

                    using (SqlCommand cmd = new SqlCommand())
                    {

                        conn.Open();

                        cmd.Connection = conn;

                        cmd.CommandType = CommandType.StoredProcedure;

                        cmd.CommandText = "proc_UpdateInventory";

                        Random random = new Random();

                        SqlParameter[] paras = new SqlParameter[]

                    {

                        new SqlParameter()

                        {

                            ParameterName = "@GoodsId",

                            SqlDbType = SqlDbType.Int,

                            Value =  random.Next(1, 4)

                        },

                        new SqlParameter()

                        {

                            ParameterName = "@Inventory",

                            SqlDbType = SqlDbType.Int,

                            Value = random.Next(1, 100)

                        }

                    };

                        cmd.Parameters.AddRange(paras);

                        int rowCount = cmd.ExecuteNonQuery();   //exec proc_UpdateInventory @GoodsId=1,@Inventory=25

                        if (rowCount > 0)


                            CommonHelper.AppLogger.InfoFormat("商品:{0},库存已更新,新的库存为:{1}", paras[0].Value, paras[1].Value);

                        else

                            CommonHelper.AppLogger.InfoFormat("更新商品库失败,无受影响记录:{0}", rowCount);

                    }

                }

            }

            catch (Exception ex)
            {

                CommonHelper.AppLogger.ErrorFormat("UpdateInventoryJob 作业执行异常:{0}", ex);

            }
        }
    }
View Code

六、CommonHelper

  class CommonHelper
    {
        public static readonly ILog AppLogger = log4net.LogManager.GetLogger("ColoredConsoleAppender");
        static CommonHelper() { }
    }
View Code

七、Program中代码调用

 static void Main(string[] args)
        {
           XmlConfigurator.ConfigureAndWatch(new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "log4net.config"));

            HostFactory.Run(x => {
                x.UseLog4Net();
                x.Service<ServiceRunner>();
                x.RunAsLocalSystem();

                x.SetDescription("Quartz+TopShelf实现Windows服务作业调度的一个示例Demo");
                x.SetDisplayName("QuartzTopShelfDemo服务");
                x.SetServiceName("QuartzTopShelfDemoService");

                x.EnablePauseAndContinue();

            });
        }
View Code

八、特别注意

 这三个文件手动创建,默认是“不复制”,这里需要修改为“始终复制”

这样一个Host便可以运行起来了。

九、安装到Windows

用cmd命令行打开这个文件夹

执行命令  : HostProject.exe install

卸载:HostProject.exe uninstall

十、SQL脚本(先把存储过程执行过在运行项目)

IF ( OBJECT_ID('Goods', 'U') IS NOT NULL )
    DROP TABLE Goods;

GO

CREATE TABLE Goods
    (
      Id INT IDENTITY(1, 1)
             NOT NULL ,
      Name NVARCHAR(30) NOT NULL ,
      Inventory INT
        NOT NULL
        CONSTRAINT PK_Goods_Id PRIMARY KEY CLUSTERED ( Id ASC ) ON [PRIMARY]
    )
ON  [PRIMARY];

INSERT  INTO Goods
VALUES  ( '大米', 0 ),
        ( '香蕉', 0 ),
        ( '苹果', 0 );

SELECT  *
FROM    Goods;

IF ( OBJECT_ID('proc_UpdateInventory', 'P') IS NOT NULL )
    DROP PROCEDURE proc_UpdateInventory;

GO

CREATE PROCEDURE proc_UpdateInventory
    (
      @GoodsId INT ,
      @Inventory INT
    )
AS
    UPDATE  Goods
    SET     Inventory = @Inventory
    WHERE   Id = @GoodsId;

GO
View Code

十一、说明

  这里没有对使用进行说明,还有Owin的还没用,后面有时间会补上。

十二、效果

原文地址:https://www.cnblogs.com/myloveblogs/p/9960129.html