buguge - Keep it simple,stupid

知识就是力量,但更重要的,是运用知识的能力why buguge?

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

Thread.Sleep引发ThreadAbortException异常

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

构造方法的代码如下:

复制代码
public Log()
{
            //开启线程负责将日志写入到指定地点
            ThreadPool.QueueUserWorkItem(o =>
            {
                try
                {
                    while (true)
                    {
                        if (_messageQueue.Count > 0)
                        {
                            lock (_messageQueue)
                            {
                                while (_messageQueue.Count > 0)
                                {
                                    LogMessage logMessage = _messageQueue.Dequeue();
                                    WriteFile(logMessage);
                                }
                            }
                        }
                        else
                        {
                            Thread.Sleep(300);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogMessage log = new LogMessage() { Content = "构造器执行报错:" + ex.ToString() };
                    FileHelper.WriteFile(string.Format(@"{0}\{1:yyyy-MM-dd}-LOGERROR.txt", _logPath, DateTime.Now), log.GetFormattedLog());
                }
            });
}
复制代码

 

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

复制代码
时间:2016-08-02 10:23:01
构造器执行报错:System.Threading.ThreadAbortException: 正在中止线程。
   在 System.Threading.Thread.SleepInternal(Int32 millisecondsTimeout)
   在 Common.Log.<.ctor>b__1(Object o)
-------------------------------------------------------------------------------
时间:2016-08-02 10:47:32
构造器执行报错:System.Threading.ThreadAbortException: 正在中止线程。
   在 System.Threading.Thread.SleepInternal(Int32 millisecondsTimeout)
   在 Common.Log.<.ctor>b__2(Object o)
----------------------------------------------------------------------------------------
复制代码

 

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

 

微软官方对ThreadAbortException的介绍:

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

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

复制代码
using System;
using System.Threading;
using System.Security.Permissions;

public class ThreadWork {
    public static void DoWork() {
        try {
            for(int i=0; i<100; i++) {
                Console.WriteLine("Thread - working."); 
                Thread.Sleep(100);
            }
        }
        catch(ThreadAbortException e) {
            Console.WriteLine("Thread - caught ThreadAbortException - resetting.");
            Console.WriteLine("Exception message: {0}", e.Message);
            Thread.ResetAbort();
        }
        Console.WriteLine("Thread - still alive and working."); 
        Thread.Sleep(1000);
        Console.WriteLine("Thread - finished working.");
    }
}

class ThreadAbortTest {
    public static void Main() {
        ThreadStart myThreadDelegate = new ThreadStart(ThreadWork.DoWork);
        Thread myThread = new Thread(myThreadDelegate);
        myThread.Start();
        Thread.Sleep(100);
        Console.WriteLine("Main - aborting my thread.");
        myThread.Abort();
        myThread.Join();
        Console.WriteLine("Main ending."); 
    }
}
复制代码

 

运行结果:

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

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

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

 

posted on   buguge  阅读(3279)  评论(0编辑  收藏  举报

编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
· 全程使用 AI 从 0 到 1 写了个小工具
点击右上角即可分享
微信分享提示