回到目录

ThreadStatic

ThreadStatic是C#里的一个特性,它可以让你的字段在一个线程里有效,但你不能控制这个字段在何时被回收,即如果声明一个int32的字段为ThreadStatic,然后你为它赋值时为100,那么它什么被恢复成默认值0,我们不得而知,这在开发时,我们可能只有手动将它设为0才行,比较难看,但也没办法,谁让咱们用了ThreadStatic呢,被声明为ThreadStatic之后,已经证明这个字段是静态化的,只不过它是被局限在一个线程内的。

Quartz

Quartz是一个任务调度框架,起源于java,它目前被广泛的使用在各种后台处理数据的场合,像一些统计数据,推送数据,消息数据等,它可以大大降低前端服务器的并发压力,并且Quartz的管理界面也有很多,直接nuget安装即可,在这些产品中最知名的应该就是CrystalQuartz了,它可以在WEB界面中管理咱们的JOB项目!

日志系统Lind.DDD.Logger

Logger本来是Lind框架的一个日志组件,它是最低层的组件,是其它组件的基础,也被用到其它的业务系统里,而其中一个Quartz组件里,使用Logger时提出了一个问题,就是如何根据job去自动建立日志目录,让每个JOB都有自己的目录,这样在分析日志时还是很有必要的。

希望看到的结果如图

aaarticlea/png;base64,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" alt="" />

测试用的两个Job

   public class Hello_Job : JobBase
{ protected override void ExcuteJob()
{ Console.WriteLine("Hello Job方法:" + Thread.CurrentThread.ManagedThreadId);
Lind.DDD.Logger.LoggerFactory.Instance.Logger_Info("Hello Job日志!");
}
} public class Hi_Job : Lind.DDD.QuartzJob.JobBase
{ protected override void ExcuteJob()
{ Console.WriteLine("Hi Job!" + Thread.CurrentThread.ManagedThreadId);
Lind.DDD.Logger.LoggerFactory.Instance.Logger_Info("Hi Job!"); }
}

JobBase做于所有Job的基类存在,它主要有自己的抽象方法和IJob的接口方法,其中抽象方法由字类Job自己去实现,去实现自己的业务逻辑;而IJob方法由Quartz框架去调用,并在方法中自己调用了抽象方法的内容,大致代码如下

    [DisallowConcurrentExecution()]
public abstract class JobBase : IJob
{ #region IJob 成员
/// <summary>
/// Job主方法
/// </summary>
/// <param name="context"></param>
public void Execute(IJobExecutionContext context)
{
Lind.DDD.Logger.LoggerFactory.Instance.SetPath(this.GetType().Name);
ExcuteJob();
Console.WriteLine(DateTime.Now.ToString() + "{0}这个Job开始执行", context.JobDetail.Key.Name);
} #endregion /// <summary>
/// Job具体类去实现自己的逻辑
/// </summary>
protected abstract void ExcuteJob();
}

日志组件中的字段使用了ThreadStatic

对日志文件分文件夹存储,主要在日志组件中使用ThreadStatic来实现的,代码主要如下

        /// <summary>
/// 每个子类初始时都执行基类这个构造,初始化当前路径
/// </summary>
public LoggerBase()
{
FileUrl = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "LoggerDir");
}
/// <summary>
/// 日志文件地址
/// 优化级为mvc方案地址,网站方案地址,console程序地址
/// </summary>
[ThreadStatic]
static protected string FileUrl;
       #region ILogger 成员
public void SetPath(string path)
{
if (!string.IsNullOrWhiteSpace(path))
{
FileUrl = FileUrl + "\\" + path;
}
}
#endregion

对于FileLogger这个文件日志实现类来说,它要做的是,在写完文件流之后,要把FileUrl这个字段从新赋值,因为我们不知道这个字符串什么时候被清空!

           lock (objLock)//防治多线程读写冲突
{
using (System.IO.StreamWriter srFile = new System.IO.StreamWriter(filePath, true))
{
srFile.WriteLine(string.Format("{0}{1}{2}"
, DateTime.Now.ToString().PadRight()
, ("[ThreadID:" + Thread.CurrentThread.ManagedThreadId.ToString() + "]").PadRight()
, message));
srFile.Close();
srFile.Dispose();
}
}
//清除当前的路径
FileUrl = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "LoggerDir");

上面的问题,我也是找了很久,因为总是找不到测试不成功的原因,最后想到了ThreadStatic特性的声明周期,算是找到根源了,呵呵!

建议大家看看C#的《对象的生与死》!

回到目录

基础才是重中之重~关于ThreadStatic和Quartz的一点渊源的更多相关文章

  1. WPF MVVM UI分离之《交互与数据分离》 基础才是重中之重~delegate里的Invoke和BeginInvoke 将不确定变为确定系列~目录(“机器最能证明一切”) 爱上MVC3系列~全局异常处理与异常日志 基础才是重中之重~lock和monitor的区别 将不确定变成确定~我想监视我的对象,如果是某个值,就叫另一些方法自动运行 将不确定变成确定~LINQ DBML模型可以对

    WPF MVVM UI分离之<交互与数据分离>   在我们使用WPF过程中,不可避免并且超级喜欢使用MVVM框架. 那么,使用MVVM的出发点是视觉与业务逻辑分离,即UI与数据分离 诸如下 ...

  2. 基础才是重中之重~方法override详解

    回到 目录 之所以写这篇文章,完全是因为这次代码审核,这次代码审核过程当中,出现了很多我认为基础知识不够扎实的问题,所以,打算把它们记录下来,共大家分享. 方法的override,即方法的覆写或者重写 ...

  3. 基础才是重中之重~ConcurrentDictionary让你的多线程代码更优美

    回到目录 ConcurrentDictionary是.net4.0推出的一套线程安全集合里的其中一个,和它一起被发行的还有ConcurrentStack,ConcurrentQueue等类型,它们的单 ...

  4. 基础才是重中之重~stream和byte[]的概念与转化

    回到目录 多看几篇 之所以写这篇文章完全是因为最近在研究FastDFS这个分布式的文件存储系统,当然这不是我第一次研究它了,就像我们去看一本书,我们不会只看一篇,而是一次次,一篇篇,每看一次会有新的收 ...

  5. 基础才是重中之重~理解linq中的groupby

    linq将大部分SQL语句进行了封装,这使得它们更加面向对象了,对于开发者来说,这是一件好事,下面我从基础层面来说一下GroupBy在LINQ中的使用. 对GroupBy的多字段分组,可以看我的这篇文 ...

  6. 基础才是重中之重~lock和monitor的区别

    回到目录 Monitor的介绍 1.Monitor.Enter(object)方法是获取锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用的两个方法,当然在使用过程中 ...

  7. C# 基础才是重中之重~对象的生与死

    为何要写 之所以写这篇文章,完全是因为学生们在实际开发中遇到的问题,一个对象占用的内存空间总不被释放,导致系统内存不断攀升,其最主要原因是我们对“对象的生与死”不清楚,或者从来没有认真去考虑过这件事, ...

  8. 基础才是重中之重~Emit动态构建方法(参数和返回值)

    回到目录 对于Emit我们知道它的可以动态构建程序集,类型,方法,属性等,或者说只要手动使用C#创建的东西使用Emit也都可以动态创建它们,Emit由于它的特别之处,所以在很多领域得到了广泛的应用,像 ...

  9. 基础才是重中之重~LazyInitializer.EnsureInitialized对属性实现化的性能优化

    回到目录 LazyInitializer.EnsureInitialized是frameworks4.0引入的新东西,实现对属性延时初始化的功能,它作用在System.Threading命名空间下,所 ...

随机推荐

  1. YIi2 Pjax简单使用

    1.点击事件需要在Pjax::begin() 和Pjax::end()范围内 2.需要在链接配置数组后加上  ['data-pjax'=>'#testPjax'] 其中,'#testPjax‘是 ...

  2. canvas基础—图形变换

    1.canvas转换方法 1.1canvas转换方法 二.canvas实现图形的中心点旋转 step1:获取canva元素并指定canvas的绘图环境 var canvas=document.getE ...

  3. (18)IO流之字节缓冲路

    缓冲流 BufferedInputStream 缓冲输入流 前面的练习告诉我们使用缓冲数组读取的效率更高,为了方便的大家的操作,sun 位大家提供了一个缓冲输入字节流对象,让我们可以更高效率的读取文件 ...

  4. CSS: 首字母字体变大时下划线不对齐的解决方法

    昨天在写2017年百度ife任务六的时候遇到了一个排版问题,需要首字母字体变大的同时,下划线对齐. 首先使用了 ::first-letter伪元素的选择器,将字体变大后,发现下划线没法对齐,代码如下: ...

  5. UWP Composition API - New FlexGrid 锁定行列

    如果之前看了 UWP Jenkins + NuGet + MSBuild 手把手教你做自动UWP Build 和 App store包 这篇的童鞋,针对VS2017,需要对应更新一下配置,需要的童鞋点 ...

  6. CentOS 安装 clamav

    1.配置yum源 # cd /etc/yum.repos.d/ # vi dag.repo写入下列内容 #Dag RPM Repository Start[dag]name=Dag RPM Repos ...

  7. Linux之uniq命令

    uniq - report or omit repeated lines  省去重复的行 参数: -i  忽略大小写字符的不同 -c  对重复的行进行记数 注意:uniq命令只会对相邻的重复的行进行去 ...

  8. PHP GD库生成图片自动换行函数,自动分页函数

    /* 文字自动换行     * @param $card 画板     * @param $pos 数组,top距离画板顶端的距离,fontsize文字的大小,width宽度,left距离左边的距离, ...

  9. 函数调用过程&生成器解释

    摘自马哥解答,感谢. 函数调用过程: 假设程序是单进程,单执行流,在某一时刻,能运行的程序流只能有一个.但函数调用会打开新的执行上下文,因此,为了确保main函数可以恢复现场,在main函数调用其它函 ...

  10. C#.Net面试题

    点这里,有很多篇<C#..Net经典面试题02> 在线阅读本文:http://3y.uu456.com/bp_5dcve363vi7px008u2lt_1.html C#..Net经典面试 ...