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方式 在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别. ...
随机推荐
- “System.Data.SqlClient.SqlConnection”的类型初始值设定项引发异常---解决方案
"System.Data.SqlClient.SqlConnection"的类型初始值设定项引发异常 问题出在了 .net 的C:\WINDOWS\Microsoft.NET\Fr ...
- SqlServer阅读收集
1.根据字段名,查找相关表--INFORMATION_SCHEMA.COLUMNS SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME ...
- Servlet执行流程和生命周期【慕课网搬】
Servlet执行流程(GET方式为例) 首先用户客户端浏览器发出Get方式(点击超链接方式)向浏览器发出请求. 服务器接收到客户端点击超链接,接收到GET请求之后,服务器到WEB.xml中<s ...
- redis之(二十一)redis之深入理解Spring Redis的使用
关于spring redis框架的使用,网上的例子很多很多.但是在自己最近一段时间的使用中,发现这些教程都是入门教程,包括很多的使用方法,与spring redis丰富的api大相径庭,真是浪费了这么 ...
- ubuntu系统lamp环境搭建、数据库迁移、设置数据库外部访问
sudo passwd root设置两次密码su输入设置的密码exit (退出root帐号) 1.sudo apt-get update 2.sudo apt-get install apache2 ...
- js 防止页面后退的方法
//防止页面后退 history.pushState(null, null, document.URL); window.addEventListener('popstate', function ( ...
- BRISK: Binary Robust Invariant Scalable Keypoints
注意:本文含有一些数学公式,如果chrome不能看见公式的话请用IE打开网站 1.特征点提取 特征点提取有以下几个步骤: a.尺度空间金字塔结构的构造 和SIFT类似,尺度空间金字塔是由不同的尺度 ...
- WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED解决方法
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ WARNING: REMOTE HOST IDENTIFICATION ...
- c#变量缺少using引用,如何快速加上using,加Using的快捷键[bubuko.com]
在vs的“工具”->“选项”中,左侧树形菜单,“环境”下的“键盘”中设置快捷键. 在“显示命令包含”输入框内输入“显示智能标记”,找到“视图.显示智能标记”,可以看到该命令的快捷键已经分配了2个 ...
- RDLC An unexpected error occurred while compiling expressions. Native compiler return value: '-1073741511'
One of my web project, which has a rdlc file using some expressions, was working fine while developi ...