统一的线程异常处理
2009-12-26 22:48
369 查看
在一个Service程序中, 通常都会有多个Worker线程,它们可能单独运行, 也可能在一个ThreadPool中运行。为了不至于使Worker线程的未处理异常导致主程序的崩溃,我们需要对所有的工作线程以一种一致的方式处理异常,例如通知主线程,然后根据不同的异常做不同的处理,最后优雅地停止该有问题的线程。 例如以下程序:
在该程序中,我们有 Worker_1 和 Worker_2两个工作线程,它们有相同的异常处理过程。但是问题是,当任务的种类多了起来,如Worker_3, Worker_4, 所有的这样的线程函数都要做相同的异常处理,就导致了不必要的重复,并且很容易遗忘。怎样去除这种重复呢?首先想到的是一个方案是,提供一个辅助函数,它接受一个Action作为参数:
然后Worker_1 可以这么写:
这样是能简化一些。但这种做法会使原来的Worker方法有一个奇怪的包装,而且依然要求我们对每一个Worker做同样的处理。既然Thread的构造函数接受一个 ThreadStart的参数,我们能不能把一个原始的直接的Worker 方法(也是 ThreadStart类型)转换为一个可以处理异常的 ThreadStart 类型呢? 是可以的。首先我们定义这个转换函数如下:
那么我们的Worker线程会很直接:
而主程序则需要稍加改动,但也非常简单:
这对线程函数的编写者来说, 减轻了很多负担, 也不至于会遗漏掉某个线程没被处理。做一次简单的搜索就可以解决问题。
对于接受一个参数的线程(ParameterizedThreadStart)和线程池线程 (WaitCallback),我们又该如何处理呢?
static void Main(string[] args) { Thread thread1 = new Thread((ThreadStart)Worker_1); thread1.Start(); Thread thread2 = new Thread((ThreadStart)Worker_2); thread2.Start(); thread1.Join(); thread2.Join(); } static void Worker_1() { try { // Do something here. } catch (Exception e) { // TODO, handler exception, // Notify the main thread and stop this thread gracefully. } } static void Worker_2() { try { // Do something here. } catch (Exception e) { // TODO, handler exception, // Notify the main thread and stop this thread gracefully. } }
在该程序中,我们有 Worker_1 和 Worker_2两个工作线程,它们有相同的异常处理过程。但是问题是,当任务的种类多了起来,如Worker_3, Worker_4, 所有的这样的线程函数都要做相同的异常处理,就导致了不必要的重复,并且很容易遗忘。怎样去除这种重复呢?首先想到的是一个方案是,提供一个辅助函数,它接受一个Action作为参数:
static void SafeThread(Action action) { try { action(); } catch (Exception e) { // TODO, handler exception, // Notify the main thread and stop this thread gracefully. } }
然后Worker_1 可以这么写:
static void Worker_1() { SafeThread(delegate { // Do something here. }); }
这样是能简化一些。但这种做法会使原来的Worker方法有一个奇怪的包装,而且依然要求我们对每一个Worker做同样的处理。既然Thread的构造函数接受一个 ThreadStart的参数,我们能不能把一个原始的直接的Worker 方法(也是 ThreadStart类型)转换为一个可以处理异常的 ThreadStart 类型呢? 是可以的。首先我们定义这个转换函数如下:
static ThreadStart SafeThread(ThreadStart threadStart) { return () => { try { threadStart(); } catch (Exception e) { // TODO, handler exception, // Notify the main thread and stop this thread gracefully. } }; }
那么我们的Worker线程会很直接:
static void Worker_1() { Console.WriteLine("Worker 1"); // Do something here. } static void Worker_2() { Console.WriteLine("Worker 2"); // Do something here. }
而主程序则需要稍加改动,但也非常简单:
static void Main(string[] args) { Thread thread1 = new Thread(SafeThread(Worker_1)); thread1.Start(); Thread thread2 = new Thread(SafeThread(Worker_2)); thread2.Start(); thread1.Join(); thread2.Join(); }
这对线程函数的编写者来说, 减轻了很多负担, 也不至于会遗漏掉某个线程没被处理。做一次简单的搜索就可以解决问题。
对于接受一个参数的线程(ParameterizedThreadStart)和线程池线程 (WaitCallback),我们又该如何处理呢?
相关文章推荐
- 统一的异常处理
- Android异常统一处理
- 使用Spring MVC统一异常处理实战
- Spring Boot 系列(八)@ControllerAdvice 拦截异常并统一处理
- springmvc 统一异常处理
- Java线程学习笔记(两) 线程异常处理
- js构建ui的统一异常处理方案(一)
- spring mvc异常统一处理(ControllerAdvice注解)
- 线程池异常统一处理
- spring mvc异常统一处理(ControllerAdvice注解)
- Web层框架对网站中所有异常的统一处理
- 【转】Spring mvc 统一异常处理和静态文件的配置
- Go语言中统一异常处理实现方式
- 使用Spring MVC统一异常处理实战<转>
- 统一处理jquery ajax请求过程中的异常错误信息的机制
- springmvc 高级3 之 统一异常处理
- Spring MVC的Controller统一异常处理:HandlerExceptionResolver
- 项目异常统一处理-spring+springmvc
- springboot统一异常处理