try-catch-finally 引发的奇怪问题
今天,发现我们的一个Windows Service无法正常停止,无奈之下只能杀了进程。
为了找到原因,我在本地进行调试,发现程序里用到了多线程,而代码正是卡在了workThread.Abort()语句而无法停止。
为什么不能Abort? 继续看线程调用的方法的代码,发现没有什么特殊的代码,只是在其中用了Thread.Sleep进行长时间等待。
难道是这个引起的? 写了一个测试程序验证,
class Program
{
private readonly Thread workThread; public Program()
{
workThread = new Thread(DoWork);
} static void Main(string[] args)
{
new Program().Work();
Console.ReadLine();
} private void Work()
{
workThread.Start();
Thread.Sleep(1 * 1000); Console.WriteLine("aborting");
workThread.Abort();
Console.WriteLine("aborted");
} private void DoWork()
{
Console.WriteLine("started");
Thread.Sleep(300 * 1000);
}
}
发现可以正常终止。
started
aborting
aborted
再仔细检查,发现其中一处Thread.Sleep放在了finally块中,修改测试代码
class Program
{
private readonly Thread workThread; public Program()
{
workThread = new Thread(DoWork);
} static void Main(string[] args)
{
new Program().Work();
Console.ReadLine();
} private void Work()
{
workThread.Start();
Thread.Sleep( * );
Console.WriteLine("aborting");
workThread.Abort(); Console.WriteLine("aborted");
} private void DoWork()
{
try
{
Console.WriteLine("started");
}
catch (Exception)
{
throw;
}
finally
{
for (int i = ; i < ; i++)
{
Console.WriteLine("ThreadState:" + workThread.ThreadState);
Thread.Sleep();
}
}
}
}
输出:
started
ThreadState:Running
aborting
ThreadState:AbortRequested
ThreadState:AbortRequested
aborted
MSDN是这样解释的:
线程不一定会立即中止,或者根本不中止。 如果线程在作为中止过程的一部分被调用的 finally 块中做非常大量的计算,从而无限期延迟中止操作,则会发生这种情况。 http://msdn.microsoft.com/zh-cn/library/5b50fdsz.aspx
其实追根溯源,问题是出在程序员对try-catch-finally的滥用上,finally块应该是用来做一些收尾工作,而不是等待操作。
finally 块用于清除 try 块中分配的任何资源,以及运行任何即使在发生异常时也必须执行的代码。 http://msdn.microsoft.com/zh-cn/library/zwc8s4fz%28v=vs.80%29.aspx
找到了原因,解决方案也挺简单,将Thread.Sleep从finally块中移除即可。
try-catch-finally 引发的奇怪问题的更多相关文章
- 移动页面click延迟引发的touch问题
一.事件捕获与冒泡 先扯一下事件的触发流程,这个之后会用到. DOM2级事件规定事件包括三个阶段: ① 事件捕获阶段 ② 处于目标阶段 ③ 事件冒泡阶段 大概的流程就是事件从最外层一层一层往里面传递( ...
- [转] C++ try catch() throw 异常处理
原文地址 其它很多程序员一样,本书的主人公阿愚也是在初学C++时,在C++的sample代码中与异常处理的编程方法初次邂逅的,如下: // Normal program statements . ...
- 异常处理(try catch throw)详解(C++)
选择异常处理的编程方法的具体原因如下: 1.把错误处理和真正的工作分开来: 2.代码更易组织,更清晰,复杂的工作任务更容易实现: 3.毫无疑问,更安全了,不至于由于一些小的疏忽而使程序意外崩溃了: 4 ...
- 小型单文件NoSQL数据库SharpFileDB初步实现
小型单文件NoSQL数据库SharpFileDB初步实现 我不是数据库方面的专家,不过还是想做一个小型的数据库,算是一种通过mission impossible进行学习锻炼的方式.我知道这是自不量力, ...
- 12、uwp 开发的零碎总结
1.在给位 “修正版本号”(Major.Minor.Build.Revision)不能修改. 后, 商店上传失败,描述信息为:Apps are not allowed to have a Versio ...
- 了解CAdoSqlserver
include <vector> 表示引用了vector类, vector是STL中的一种数据结构,或者叫容器,功能相当于数组,但是功能强大很多.vector在C++标准模板库中的部分内容 ...
- #pragma once与#ifndef #define ...#endif的区别
1. #pragma once用来防止某个头文件被多次include: #ifndef,#define,#endif用来防止某个宏被多次定义. 2. #pragma once是编译相关,就是说这个 ...
- Oracle软件安装目录满的清理方法
这是Oracle数据库日常运维中很常见的一个场景,安装目录满有时不光会导致无法记录最新数据库的日志信息,导致遇到问题无法查到最新的日志信息,还会引发一些奇怪的问题. 所以日常巡检要保证Oracle的安 ...
- #pragma once与 #ifndef的区别
为了避免同一个文件被include多次 1 #ifndef方式2 #pragma once方式 在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别. ...
随机推荐
- Flat UI 工具包
Flat UI是一套精美的扁平风格 UI 工具包,基于 Twitter Bootstrap 实现.这套界面工具包含许多基本的和复杂的 UI 部件,例如按钮,输入框,组合按钮,复选框,单选按钮,标签,菜 ...
- 备忘录模式(Memento Pattern)
在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 备忘录模式主要思想是——利用备忘录对象来对保存发起人的内部状态,当发起人需要恢复原 ...
- u-boot-2010.09移植(A)
第一阶段 1.开发环境 系统:centOS6.5 linux版本:2.6.32 交叉编译器:buildroot-2012.08 以上工具已经准备好,具体安装步骤不再 ...
- Android 启动模式及常用的Intent的Flag
LaunchMode 在声明Activity的xml中指定 android:launchMode="xxx" standard 标准模式.这是系统默认的模式,每次启动Activit ...
- android源码的目录结构
android源码的目录结构 [以下网络摘抄] |-- Makefile ! l/ a5 n% S% @- `0 d# z# a$ P4 V3 o7 R|-- bionic ...
- IT荐书|10个最“牛叉”的代码注释
下面是 网友针对“你看到过的最好的代码注释是什么样的?”这个问题给出的回答的前10条: 1. // 亲爱的维护者: // 如果你尝试了对这段程序进行‘优化’, // 并认识到这种企图是大错特错,请增加 ...
- HTML中strong与b,em与i标签的区别
先看效果 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <titl ...
- Netty服务端与客户端(源码一)
首先,整理NIO进行服务端开发的步骤: (1)创建ServerSocketChannel,配置它为非阻塞模式. (2)绑定监听,配置TCP参数,backlog的大小. (3)创建一个独立的I/O线程, ...
- 116、Android获取Manifest中<meta-data>元素的值
在AndroidManifest.xml中,<meta-data>元素可以作为子元素, 被包含在<activity>.<application> .<serv ...
- shell条件判断中-a至-z的含义
[ -a file ] ------- 如果file存在,返回值为真. [ -b file ] ------- 如果file存在且为块特殊文件,返回值为真. [ -c file ] ------- 如 ...