短信平台记录日志模块,是通过异步方式来记录的,即日志工具类里初始化一个Queue对象,公共的写日志方法的处理逻辑是把日志消息放到Queue里。构造器里设定一个死循环,不停的读队,然后把日志消息持久化到磁盘的文本文件里。

构造方法的代码如下:

  1. public Log()
  2. {
  3. //开启线程负责将日志写入到指定地点
  4. ThreadPool.QueueUserWorkItem(o =>
  5. {
  6. try
  7. {
  8. while (true)
  9. {
  10. if (_messageQueue.Count > )
  11. {
  12. lock (_messageQueue)
  13. {
  14. while (_messageQueue.Count > )
  15. {
  16. LogMessage logMessage = _messageQueue.Dequeue();
  17. WriteFile(logMessage);
  18. }
  19. }
  20. }
  21. else
  22. {
  23. Thread.Sleep();
  24. }
  25. }
  26. }
  27. catch (Exception ex)
  28. {
  29. LogMessage log = new LogMessage() { Content = "构造器执行报错:" + ex.ToString() };
  30. FileHelper.WriteFile(string.Format(@"{0}\{1:yyyy-MM-dd}-LOGERROR.txt", _logPath, DateTime.Now), log.GetFormattedLog());
  31. }
  32. });
  33. }

近期通过看线上站点日志,发现不定期会有ThreadAbortException被捕获,

  1. 时间:-- ::
  2. 构造器执行报错:System.Threading.ThreadAbortException: 正在中止线程。
  3. System.Threading.Thread.SleepInternal(Int32 millisecondsTimeout)
  4. Common.Log.<.ctor>b__1(Object o)
  5. -------------------------------------------------------------------------------
  6. 时间:-- ::
  7. 构造器执行报错:System.Threading.ThreadAbortException: 正在中止线程。
  8. System.Threading.Thread.SleepInternal(Int32 millisecondsTimeout)
  9. Common.Log.<.ctor>b__2(Object o)
  10. ----------------------------------------------------------------------------------------

通过分析,当站点应用程序池回收或遇到其他未捕获的异常时,线程会被Abort,这时,当线程里的代码再被执行时,就会抛出ThreadAbortException异常。

微软官方对ThreadAbortException的介绍:

在调用 Abort 方法以销毁线程时,CLR将引发ThreadAbortExceptionThreadAbortException 是一种可捕获的特殊异常,但在 catch 块的结尾处它将自动被再次引发。引发此异常时,运行库将在结束线程前执行所有 finally 块。由于线程可以在 finally 块中执行未绑定计算,或调用 Thread.ResetAbort 来取消中止,所以不能保证线程将完全结束。如果您希望一直等到被中止的线程结束,可以调用 Thread.Join 方法。Join 是一个模块化调用,它直到线程实际停止执行时才返回。

下面的示例说明如何中止线程。接收 ThreadAbortException 的线程使用 ResetAbort 方法取消中止请求并继续执行。

  1. using System;
  2. using System.Threading;
  3. using System.Security.Permissions;
  4.  
  5. public class ThreadWork {
  6. public static void DoWork() {
  7. try {
  8. for(int i=; i<; i++) {
  9. Console.WriteLine("Thread - working.");
  10. Thread.Sleep();
  11. }
  12. }
  13. catch(ThreadAbortException e) {
  14. Console.WriteLine("Thread - caught ThreadAbortException - resetting.");
  15. Console.WriteLine("Exception message: {0}", e.Message);
  16. Thread.ResetAbort();
  17. }
  18. Console.WriteLine("Thread - still alive and working.");
  19. Thread.Sleep();
  20. Console.WriteLine("Thread - finished working.");
  21. }
  22. }
  23.  
  24. class ThreadAbortTest {
  25. public static void Main() {
  26. ThreadStart myThreadDelegate = new ThreadStart(ThreadWork.DoWork);
  27. Thread myThread = new Thread(myThreadDelegate);
  28. myThread.Start();
  29. Thread.Sleep();
  30. Console.WriteLine("Main - aborting my thread.");
  31. myThread.Abort();
  32. myThread.Join();
  33. Console.WriteLine("Main ending.");
  34. }
  35. }

运行结果:

  1. Thread - working.
  2. Main - aborting my thread.
  3. Thread - caught ThreadAbortException - resetting.
  4. Exception message: Thread was being aborted.
  5. Thread - still alive and working.
  6. Thread - finished working.
  7. Main ending.

————————————————————–我是萌萌哒分界线————————————————————

生产者/消费者模式
我们系统里的日志Helper类用到了Queue来实现异步记日志,提高系统容错和性能。现在想来,这就是一个生产者/消费者模式的运用。
在分布式系统中,这个模式更适用,尤其是消息处理。 RabbitMQ正是基于这种需求而产生的消息中间件。
 

Thread.Sleep引发ThreadAbortException异常的更多相关文章

  1. C# Thread.Abort方法与ThreadAbortException异常(取消线程与异常处理)

    1.Abort当前线程,后续程序不会执行 class Program { public static Thread thread1; static void Main(string[] args) { ...

  2. 选择目录,选择文件夹的COM组件问题。在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。请确保您的 Main 函数带有 STAThreadAttribute 标记。 只有将调试器附加到该进程才会引发此异常。

    异常: 在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式.请确保您的 Main 函数带有 STAThreadAttribute 标记. 只有将调试器附加到该进程才会引发此异常. ...

  3. Response.End()出现ThreadAbortException 异常

    A. 如果使用 Response.End.Response.Redirect 或 Server.Transfer 方法,将出现 ThreadAbortException 异常.异常内容:由于代码已经过 ...

  4. c# Clipboard.SetDataObject(bmp1) 在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。请确保您的 Main 函数带有 STAThreadAttribute 标记。 只有将调试器附加到该进程才会引发此异常

    c# Clipboard.SetDataObject(bmp1)  在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式.请确保您的 Main 函数带有 STAThreadAttri ...

  5. Response.End抛出ThreadAbortException 异常

    最近在写程序过程中遇到了一个匪夷所思的错误:Response.End()方法抛出了ThreadAbortException异常,我的代码如下: public void doResponse(){ st ...

  6. 将不确定变为确定~DateTime.MinValue和MaxValue引发的异常

    回到目录 问题描述: SqlDateTime 溢出.必须介于 1/1/1753 12:00:00 AM 和 12/31/9999 11:59:59 PM 之间 概念相关 .Net中的DateTime结 ...

  7. WPF控件ComboBox 每个Item的ToolTip引发的异常

    介绍 首先介绍下要实现的任务.做一个下拉框,当选择每个项的时候将鼠标发在上面显示该项的ToolTip的内容(Image). 实现 Model: public class SkinInfo : Noti ...

  8. VS2010 F5调试时出现:“ 尝试运行项目时出错:未捕获通过反射调用的方法引发的异常”解决

    VS2010 F5调试时出现 尝试运行项目时出错:未捕获通过反射调用的方法引发的异常 两个解决方法:1) 打开项目属性,选择调试选项卡,将“启用非托管代码调试”一项钩上.2) 打开项目属性,选择调试选 ...

  9. WPF关于“在“System.Windows.Markup.StaticResourceHolder”上提供值时引发了异常。”问题解决办法

    在WPF中添加样式,在MainWindow.xaml使用自定义按钮FButton时报错,报错信息如下: "System.Windows.Markup.XamlParseException&q ...

随机推荐

  1. 代替jquery $.post 跨域提交数据的N种形式

    跨域的N种形式: 1.直接用jquery中$.getJSON进行跨域提交 优点:有返回值,可直接跨域: 缺点:数据量小: 提交方式:仅get (无$.postJSON) $.getJSON(" ...

  2. Idea中包内中的置文件如何发布到编译后的目录中去

    1.问题引入: 运行一个maven+springmvc+hibernate的项目的时候出现了下边的错误: Caused by: java.io.FileNotFoundException: class ...

  3. 树链剖分+线段树 HDOJ 5029 Relief grain(分配粮食)

    题目链接 题意: 分粮食我就当成涂色了.有n个点的一棵树,在a到b的路上都涂上c颜色,颜色可重复叠加,问最后每一个点的最大颜色数量的颜色类型. 思路: 首先这题的输出是每一个点最后的情况,考虑离线做法 ...

  4. java 判断两个list是否相等

    /** * 队列比较 * @param <T> * @param a * @param b * @return */ public static <T extends Compara ...

  5. Linux内核笔记——进程管理之执行体

    内核版本:linux-2.6.11 在Linux中,有多种执行体(指令流.执行单位),它们是CPU调度和分配资源的基本单位,它们是内核态可见的,即内核态下,每一种执行体都有对应的唯一数据结构task_ ...

  6. Project 'king.commons' is missing required library: 'lib/plweb.jar' Build path Build Path Problem

    问题描述:之前在项目里引用一个jar 包,后来不用了删掉 ,但是没有删干净,然后报以下错误. 解决方案: 1.删除libraries 2.找到该项目下的 .classpath 文件,用记事本打开 ,删 ...

  7. CSS样式,雪碧,图片替换,渐变小析

    Css基础2: 相对长度单位:em,rem,px,%绝对长度单位:厘米等(不用)颜色单位:rgb,rgb的百分比,16进制(#),颜色名称字体:font-size:为了更好适合点阵,尽量使用偶数fon ...

  8. Sort with Swap(0, i)

    原题连接:https://pta.patest.cn/pta/test/16/exam/4/question/678 题目如下: Given any permutation of the number ...

  9. System.Dynamic.ExpandoObject 类型的简单使用

    该类型可以实现的是动态添加属性和移除属性,有点类似 js 中对象的操作,非常灵活 static void Main(string[] args) { dynamic obj = new System. ...

  10. Red Hat5下源码安装mysql5.6过程记录

    1.安装cmake包 [root@edu soft]# tar -xzf cmake-.tar.Z [root@edu soft]# cd cmake- [root@edu cmake-]# ./co ...