惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
N
Netflix TechBlog - Medium
Google Online Security Blog
Google Online Security Blog
月光博客
月光博客
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
腾讯CDC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
M
MIT News - Artificial intelligence
Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
aimingoo的专栏
aimingoo的专栏
博客园 - 三生石上(FineUI控件)
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
MongoDB | Blog
MongoDB | Blog
H
Help Net Security
The Cloudflare Blog
Blog — PlanetScale
Blog — PlanetScale
F
Full Disclosure
G
Google Developers Blog
罗磊的独立博客
Jina AI
Jina AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
A
About on SuperTechFans
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
有赞技术团队
有赞技术团队
GbyAI
GbyAI
雷峰网
雷峰网
T
The Blog of Author Tim Ferriss
The Register - Security
The Register - Security
U
Unit 42
D
Docker
Martin Fowler
Martin Fowler
L
LINUX DO - 热门话题
NISL@THU
NISL@THU
阮一峰的网络日志
阮一峰的网络日志
C
Cybersecurity and Infrastructure Security Agency CISA
博客园_首页
Google DeepMind News
Google DeepMind News

博客园 - BearOcean

LOG.ZS.0001.基于Freetype的游戏字体渲染优化思路 const 和指针 C++ 下啥时候用struct, 啥时候用class C++ 和 Java 中的变参 解决站点关键数据,状态数据,无须持久化数据的一些思路 BS程序代码与安全与基本攻击/防御模式 Struts 实现的I18N Ant 阅读笔记 进度,效率,与个人事务管理 Personal Task 1.0 MySql与Java的时间类型 数据挖掘概述 Command 模式 .Net标准控件与自定义控件(2) ToolTipButton 内网聊天工具FreeChat 2.0 FreeChat 2.0 ...大改 模型和架构 局域网聊天工具FreeChat 1.0 开发日志 内网聊天工具FreeChat Beta 为Socket写的附加方法 .Net 事件
解决Thread 的关闭问题和参数传递时想到的办法.
BearOcean · 2006-06-13 · via 博客园 - BearOcean

在运用多线程的时候,往往会涉及到线程的关闭,很多人指出可以使用Thread.Abort方法来关闭线程.
在这里提出一些自己的想法:

参考一下牛津字典对单词Abort的解释:

vi.
异常中断, 中途失败, 夭折, 流产, 发育不全
n.
中止计划[任务]异常中断, 中途失败, 夭折, 流产, 发育不全

有夭折的意思

参考一下Abort的MSDN解释:
当线程对自身调用 Abort 时,效果类似于引发异常;ThreadAbortException 会立刻发生,并且结果是可预知的。但是,如果一个线程对另一个线程调用 Abort,则将中断运行的任何代码。在 finally 块运行时线程可能会终止,在这种情况下,finally 块将被终止。还有一种可能就是静态构造函数被终止。在极少数情况下,这可以防止在该应用程序域中创建该类的实例。

线程不一定会立即中止,或者根本不中止。如果线程在作为中止过程的一部分被调用的 finally 块中做非常大量的计算,从而无限期延迟中止操作,则会发生这种情况。

可见对Thread进行一个Abort调用,实际上是通过引发一个异常来进行强制关闭.这样对程序来说可能存在潜在的威胁.所以实际上.

相信很多人都有Abort后线程仍然运行的经历.实际上Thread结束失败是较小的损失.另外一可能会出现一种更大的威胁:
例如:

我有一个数据库.当用户更新表1时一定会更新表2中的一个字段.
假如开发中没有使用存储过程,而是把这2个更新放到了一个线程中去执行.那么就为问题的出现埋下了隐影.

用户通过一个Text ="UpDate"的按钮开启了这个线程,这个线程开始进行费事的更新操作.然而用户对执行2个操作所需要的时间没有很好的认识.在点击了这个按钮后就选择了退出系统.
好,麻烦来了.
由于Abort是强制结束,无疑在任何时间都可以把代码Kill了.如果运气不好,在刚执行了第一个更新步骤后就把线程喀嚓了...

这个问题的严重程度实际上是比较大的,做CS 的兄弟大概都知道.而且这样的错误实际上是难以发现的.
但是一但有这样的bug, 实际上可以认为系统是健壮性不高的.

所以我提出一种使用线程并且关闭线程的其他办法.

自己对线程进行一些封装:

 1public class BX_Thread
 2    {
 3        private Thread thWorker;
 4        private bool IsClosing =false;
 5
 6        private int Interval =0;
 7        private object objParameter;
 8        public BX_Thread(object Parameter)
 9        {
10            this.objParameter =Parameter;
11            this.thWorker =new Thread(new ThreadStart(WorkProc));
12            this.thWorker.Priority =ThreadPriority.Lowest;
13        }

14
15        public void Run(int Interval)
16        {
17            this.thWorker.Start();
18        }

19
20        private void WorkProc()
21        {
22            while(this.IsClosing !=true)
23            {
24                if(this.Interval !=0)
25                {
26                    Thread.Sleep(this.Interval);
27                }

28                //do something
29                                
30            }

31
32            this.thWorker =null;
33        }

34
35        public void Close()
36        {
37            this.IsClosing =true;
38        }

39    }

代码实际上很简单,无非是自己封装了一下Thread.
这样有2个好处:

(1)2003 的Thread好象是不能传递参数.将参数封装到BX_Thread中(以private object)的方式存在,可以保证Thread对他的访问.

 (2) 提供了一种非 Abort的结束方式.
 
对于最关心的地2个问题:
可以看看WorkProc().

这里有个while循环.需要解释一下.
一般来说,多线程运用到生产消费模式的情况比较多.
最典型的:我在一个线程中将数据不断的填入一个队列.
然后开很多线程不断的重队列中取出数据进行处理.

这是,线程的执行方法通常是考虑如下的结构:
WorkProc()
{
    while(true)
     {
        if(队列中有数据)
        {
            取出一个进行处理。
        }
    }
}

BX_Thread模型主要对这个模型的循环部分进行了修改。
WorkProc()
{
    while(this.IsClosing !=true)
    {
        if(队列中有数据)
        {
            取出一个进行处理。
        }
    }
}

然后提供一个方法:BX_Thread.Close()
只需要将 private bool IsClosing 改为true.
线程就会自己退出循环了。
一但退出循环,线程也就自然死亡而非谋杀了。

所以这个是一种思路。BX_Thread可以这样使用:
首先改写WorkProc()满足你的需求。
BX_Thread thWorker =new BX_Thread( Parameter);
thWorker.Run(1000);
//这里的1000回导致循环一次Sleep1秒。如果Run(0)则不Sleep..
//结束
thWorker.Close();

如果不想改写WorkProc
那么可以考虑做一个接口。将线程和业务分离。

我的意思,还有一点:并不是说Abort没有存在的价值。
有时也会有Abort起来很方便的时候。
但是大多数情况,需要Thread正常结束。
而且用错了结束的方式,也会很麻烦。

                                            BearOcean