Quartz.Net系列(十五):Quartz.Net四种修改配置的方式

案例:修改默认线程个数

1.NameValueCollection

            System.Collections.Specialized.NameValueCollection collection = new System.Collections.Specialized.NameValueCollection();

            collection.Add("quartz.threadPool.ThreadCount","20");          

            var factory= new StdSchedulerFactory(collection);

            var scheduler= await factory.GetScheduler();

            await scheduler.Start();

            var metData=await scheduler.GetMetaData();

            Console.WriteLine(metData.ThreadPoolSize);

原理

通过反射实例化对象DefaultThreadPool

            Type tpType = loadHelper.LoadType(threadPoolTypeString) ?? typeof(DefaultThreadPool);

            try
            {
                tp = ObjectUtils.InstantiateType<IThreadPool>(tpType);
            }
            catch (Exception e)
            {
                initException = new SchedulerException("ThreadPool type '{0}' could not be instantiated.".FormatInvariant(tpType), e);
                throw initException;
            }
            tProps = cfg.GetPropertyGroup(PropertyThreadPoolPrefix, true);
            try
            {
                ObjectUtils.SetObjectProperties(tp, tProps);
            }
            catch (Exception e)
            {
                initException = new SchedulerException("ThreadPool type '{0}' props could not be configured.".FormatInvariant(tpType), e);
                throw initException;
            }

设置对象的属性

 public static void SetObjectProperties(object obj, NameValueCollection props)
        {
            // remove the type
            props.Remove("type");

            foreach (string name in props.Keys)
            {
                string propertyName = CultureInfo.InvariantCulture.TextInfo.ToUpper(name.Substring(0, 1)) +
                                      name.Substring(1);

                try
                {
                    object value = props[name];
                    SetPropertyValue(obj, propertyName, value);
                }
                catch (Exception nfe)
                {
                    throw new SchedulerConfigException(
                        $"Could not parse property '{name}' into correct data type: {nfe.Message}", nfe);
                }
            }
        }

通过反射设置属性的值

 public static void SetPropertyValue(object target, string propertyName, object value)
        {
            Type t = target.GetType();

            PropertyInfo pi = t.GetProperty(propertyName);

            if (pi == null || !pi.CanWrite)
            {
                // try to find from interfaces
                foreach (var interfaceType in target.GetType().GetInterfaces())
                {
                    pi = interfaceType.GetProperty(propertyName);
                    if (pi != null && pi.CanWrite)
                    {
                        // found suitable
                        break;
                    }
                }
            }

            if (pi == null)
            {
                // not match from anywhere
                throw new MemberAccessException($"No writable property '{propertyName}' found");
            }

            MethodInfo mi = pi.GetSetMethod();

            if (mi == null)
            {
                throw new MemberAccessException($"Property '{propertyName}' has no setter");
            }

            if (mi.GetParameters()[0].ParameterType == typeof(TimeSpan))
            {
                // special handling
                value = GetTimeSpanValueForProperty(pi, value);
            }
            else
            {
                value = ConvertValueIfNecessary(mi.GetParameters()[0].ParameterType, value);
            }

            mi.Invoke(target, new[] {value});
        }

结果图

 

 

 2.App.config(只在.NETFramework生效)

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="quartz" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
    </configSections>

    <quartz>
        <add key="quartz.threadPool.ThreadCount" value="11"/>
    </quartz>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
    </startup>
</configuration>

 

        static void Main(string[] args)
        {
            var scheduler =new StdSchedulerFactory().GetScheduler().Result;

            scheduler.Start();

            var metaData=scheduler.GetMetaData().Result;

            Console.WriteLine(metaData.ThreadPoolSize);

            Console.Read();
        }

结果图

 

 

 原理

通过ConfigurationManager.GetSection()来获取App.config里面的值,如果有就转换成NameValueCollection

         public virtual void Initialize()
        {
            // short-circuit if already initialized
            if (cfg != null)
            {
                return;
            }
            if (initException != null)
            {
                throw initException;
            }

            var props = Util.Configuration.GetSection(ConfigurationSectionName);
         }

 

internal static NameValueCollection GetSection(string sectionName)
        {
            try
            {
                return (NameValueCollection) ConfigurationManager.GetSection(sectionName);
            }
            catch (Exception e)
            {
                log.Warn("could not read configuration using ConfigurationManager.GetSection: " + e.Message);
                return null;
            }
        }

3.quartz.config

quartz.threadPool.ThreadCount=20

 

            System.Collections.Specialized.NameValueCollection collection = new System.Collections.Specialized.NameValueCollection();

            //collection.Add("quartz.threadPool.ThreadCount","20");          

            //var factory= new StdSchedulerFactory(collection);

            var factory = new StdSchedulerFactory();

            var scheduler= await factory.GetScheduler();

            await scheduler.Start();

            var metData=await scheduler.GetMetaData();

            Console.WriteLine(metData.ThreadPoolSize);

结果图

 

原理

判断当前程序中是否有quartz.config这个文件

如果有则读取

            if (props == null && File.Exists(propFileName))
            {
                // file system
                try
                {
                    PropertiesParser pp = PropertiesParser.ReadFromFileResource(propFileName);
                    props = pp.UnderlyingProperties;
                    Log.Info($"Quartz.NET properties loaded from configuration file '{propFileName}'");
                }
                catch (Exception ex)
                {
                    Log.ErrorException("Could not load properties for Quartz from file {0}: {1}".FormatInvariant(propFileName, ex.Message), ex);
                }
            }

#表示注释

!END代表结束,如果没有就读取全部

        public static PropertiesParser ReadFromFileResource(string fileName)
        {
            return ReadFromStream(File.OpenRead(fileName));
        }

        private static PropertiesParser ReadFromStream(Stream stream)
        {
            NameValueCollection props = new NameValueCollection();
            using (StreamReader sr = new StreamReader(stream))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    line = line.TrimStart();

                    if (line.StartsWith("#"))
                    {
                        // comment line
                        continue;
                    }
                    if (line.StartsWith("!END"))
                    {
                        // special end condition
                        break;
                    }
                    string[] lineItems = line.Split(new[] { '=' }, 2);
                    if (lineItems.Length == 2)
                    {
                        props[lineItems[0].Trim()] = lineItems[1].Trim();
                    }
                }
            }
            return new PropertiesParser(props);
        }

4.Environment(环境变量)

            Environment.SetEnvironmentVariable("quartz.threadPool.ThreadCount","50");
           
            System.Collections.Specialized.NameValueCollection collection = new System.Collections.Specialized.NameValueCollection();

            //collection.Add("quartz.threadPool.ThreadCount","20");          

            //var factory= new StdSchedulerFactory(collection);

            var factory = new StdSchedulerFactory();

            var scheduler= await factory.GetScheduler();

            await scheduler.Start();

            var metData=await scheduler.GetMetaData();

            Console.WriteLine(metData.ThreadPoolSize);

结果图

 

 

 

 

 原理

public virtual void Initialize()
{
  。。。。。。
  Initialize(OverrideWithSysProps(props));
}

获取所有的环境变量,然后赋值给NameValueCollection

        private static NameValueCollection OverrideWithSysProps(NameValueCollection props)
        {
            NameValueCollection retValue = new NameValueCollection(props);
            IDictionary<string, string> vars = QuartzEnvironment.GetEnvironmentVariables();

            foreach (string key in vars.Keys)
            {
                retValue.Set(key, vars[key]);
            }

            return retValue;
        }

 quartz.config<app.config<环境变量<NameValueCollection