(C#) Tasks 中的异常处理(Exception Handling.)

多线程编程中要注意对线程异常的处理。首先写个例子。

一个线程用于显示信息(Show Messages)。主线程用于做其他工作(Do Works)。

            using (Task taskShowMessages = new Task(ShowMessages))
            {
                try
                {
                    taskShowMessages.Start();
                    DoWorks();
                }
                catch (DoWorkException ex)
                {
                    Console.WriteLine("Error:{0}", ex.Message);
                }
                catch(Exception ex)
                {
                    Console.WriteLine("Error:{0}", ex.Message);
                }
            }
 public static void ShowMessages()
        {
            int i = 0;
            while (true)
            {
                Console.WriteLine("{0} - Message_{1}", DateTime.Now.ToString(), i++);
                Thread.Sleep(1000); 

                if ( i == 3)
                {
                    throw new ShowMessageException(string.Format("User defined error occured during showing message_{0}!", i));
                    //throw new Exception(string.Format("Unhandled exception occured during showing message_{0}!", i));
                }
            }
        }

        public static void DoWorks()
        {
            int i = 0;
            while (true)
            {
                Console.WriteLine("{0} - DoWork_{1}", DateTime.Now.ToString(), i++);
                Thread.Sleep(2000);

                if (i == 4)
                {
                    throw new DoWorkException(string.Format("User defined error occured during doing work_{0}!", i));
                    //throw new Exception(string.Format("Unhandled exception occured during doing work{0}!", i));
                }
            }
        }

        public class ShowMessageException : Exception
        {
            public ShowMessageException(String message)
                : base(message)
            {
            }
        }

         public class DoWorkException : Exception
        {
             public DoWorkException(String message)
                : base(message)
             {
             }
        }

输出:

12/27/2015 10:08:03 PM - DoWork_0
12/27/2015 10:08:03 PM - Message_0
12/27/2015 10:08:04 PM - Message_1
12/27/2015 10:08:05 PM - DoWork_1
12/27/2015 10:08:05 PM - Message_2
12/27/2015 10:08:07 PM - DoWork_2
12/27/2015 10:08:09 PM - DoWork_3
Error:User defined error occured during doing work_4!

可以看出来,Show Message 3 时发生一个异常,但是本程序无视它并继续DoWorks。知道DoWorks发生异常抛出。
在VS的debug环境下可以看到这个异常的发生:

A first chance exception of type ‘ConsoleApplication2.Program.ShowMessageException‘ occurred in ConsoleApplication2.exe
A first chance exception of type ‘ConsoleApplication2.Program.DoWorkException‘ occurred in ConsoleApplication2.exe

如果想正确的处理ShowMessage线程的异常,必须对其 Wait()方法进行处理。

            using (Task taskShowMessages = new Task(ShowMessages))
            {
                try
                {
                    taskShowMessages.Start();
                    DoWorks();
                }
                catch (DoWorkException ex)
                {
                    Console.WriteLine("Error is handled:{0}", ex.Message);
                }
                finally
                {
                    try
                    {
                        taskShowMessages.Wait();
                    }
                    catch(AggregateException ae)
                    {
                        ae.Handle((x) =>
                            {
                                if (x is ShowMessageException)
                                {
                                    Console.WriteLine("Error is handled:{0}", x.Message);
                                    return true;
                                }
                                else
                                {
                                    return false;
                                }
                            });
                    }
                }
            }

输出:

12/27/2015 10:16:37 PM - DoWork_0
12/27/2015 10:16:37 PM - Message_0
12/27/2015 10:16:38 PM - Message_1
12/27/2015 10:16:39 PM - DoWork_1
12/27/2015 10:16:39 PM - Message_2
12/27/2015 10:16:41 PM - DoWork_2
12/27/2015 10:16:43 PM - DoWork_3
Error is handled:User defined error occured during doing work_4!
Error is handled:User defined error occured during showing message_3!

那么现在如果其中一个线程出现异常的话,我们就希望抛出异常,结束程序,怎么做?

答案就是使用:

CancellationTokenSource

        static CancellationTokenSource cancellationtoken = new CancellationTokenSource();
        static void Main(string[] args)
        {

            using (Task taskShowMessages = new Task(ShowMessages, cancellationtoken.Token))
            {
                try
                {
                    taskShowMessages.Start();
                    DoWorks();
                }
                catch (DoWorkException ex)
                {
                    Console.WriteLine("Error is handled:{0}", ex.Message);
                }
                finally
                {
                    cancellationtoken.Cancel();

                    try
                    {
                        taskShowMessages.Wait();
                    }
                    catch (AggregateException ae)
                    {
                        ae.Handle((x) =>
                            {
                                if (x is ShowMessageException)
                                {
                                    Console.WriteLine("Error is handled:{0}", x.Message);
                                    return true;
                                }
                                else
                                {
                                    return false;
                                }
                            });
                    }
                }
            }
        }

        public static void ShowMessages()
        {
            int i = 0;
            while (!cancellationtoken.IsCancellationRequested)
            {
                Console.WriteLine("{0} - Message_{1}", DateTime.Now.ToString(), i++);
                Thread.Sleep(1000); 

                if ( i == 3)
                {
                    //throw new ShowMessageException(string.Format("User defined error occured during showing message_{0}!", i));
                    //throw new Exception(string.Format("Unhandled exception occured during showing message_{0}!", i));
                    //break;
                }
            }
        }

输出:

12/27/2015 10:40:56 PM - DoWork_0
12/27/2015 10:40:56 PM - Message_0
12/27/2015 10:40:57 PM - Message_1
12/27/2015 10:40:58 PM - DoWork_1
12/27/2015 10:40:58 PM - Message_2
12/27/2015 10:40:59 PM - Message_3
12/27/2015 10:41:00 PM - DoWork_2
12/27/2015 10:41:00 PM - Message_4
12/27/2015 10:41:01 PM - Message_5
12/27/2015 10:41:02 PM - DoWork_3
12/27/2015 10:41:02 PM - Message_6
12/27/2015 10:41:03 PM - Message_7
Error is handled:User defined error occured during doing work_4!

参考:

https://msdn.microsoft.com/en-us/library/dd997415(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/dd537614(v=vs.110).aspx

时间: 2024-08-06 17:37:17

(C#) Tasks 中的异常处理(Exception Handling.)的相关文章

C#中的异常处理(Exception Process in C#)

不要抛出"new Exception()"–>抽象的异常往往让人迷惑 不要只记录Exception.Message的值,还需要记录Exception.ToString()–>Exception.ToString()包含"堆栈跟踪"信息 catch要捕捉具体异常–>好的代码只捕捉知道的异常 using使用–>异常发生时,using能放在资源泄露 新异常应将原始异常作为其内部异常 catch抛出新异常会导致call stack丢失–>不处理

C++、Java、JavaScript中的异常处理(Exception)

编程思想之异常处理 什么叫异常处理? 什么叫异常(Exception)?顾名思义就是非正常的情况,出现了不希望出现的意外,异常处理就是遇到这种意外时准备的对策和解决方案.比如您开着一辆劳斯莱斯在公路上行走,突然前面出现一个小孩,幸好您眼疾手快紧急刹车,而避免了一场交通事故.在这个例子中突然出现的小孩就是异常,紧急刹车就是异常处理(面对这种突发情况采取的解决方案). 程序来源于现实,是现实的抽象和模拟,也会有异常,因此异常的处理就显示的极为重要.试想如果您的手机的某个应用使用两下就崩溃了,或都出现

Akka(26): Stream:异常处理-Exception handling

akka-stream是基于Actor模式的,所以也继承了Actor模式的“坚韧性(resilient)”特点,在任何异常情况下都有某种整体统一的异常处理策略和具体实施方式.在akka-stream的官方文件中都有详细的说明和示范例子.我们在这篇讨论里也没有什么更好的想法和范例,也只能略做一些字面翻译和分析理解的事了.下面列出了akka-stream处理异常的一些实用方法: 1.recover:这是一个函数,发出数据流最后一个元素然后根据上游发生的异常终止当前数据流 2.recoverWithR

SEH(structured exception handling)基础篇---终止处理程序

前序:最近看SEH看的头晕脑胀/(ㄒoㄒ)/~~,SEH最开始是Windows提供的异常处理机制,只是一个简单的框架,而我们现在使用的SEH都是编译器已经在系统提供的最基础的框架上做了修改的增强版(原始版比较原始,牵扯到大量Windows基础知识,并且需要反汇编看汇编代码来理解....本人现在功力较浅,需要慢慢消化,先看一下增强版,通过C和C++来接触一下. SEH包含两部分功能:终止处理(termination handling)和异常处理(exception handling).在这先讲一下

OAF_OAF Exception Handling异常处理(概念)

2014-06-12 BaoXinjian 一.摘要 Oracle Application Framework将异常分为三类 异常类型type 1. 常规异常General Exception Class:oracle.apps.fnd.framework.OAException Function: 提供了在运行时刻同时显示多种类型异常的手段,结合EBS的Message,可显示有用的信息 2. 验证异常Validation Exception Class:oracle.apps.fnd.fram

Exception Handling in ASP.NET Web API webapi异常处理

原文:http://www.asp.net/web-api/overview/error-handling/exception-handling This article describes error and exception handling in ASP.NET Web API. HttpResponseException Exception Filters Registering Exception Filters HttpError HttpResponseException Wha

[转载]A Crash Course on the Depths of Win32 Structured Exception Handling

转自:[已完工][经典文章翻译]A Crash Course on the Depths of Win32 Structured Exception Handling 原文题目: <<A Crash Course on the Depths of Win32™ Structured Exception Handling>> 原文地址: http://www.microsoft.com/msj/0197/Exception/Exception.aspx 原作者: Matt Pietr

【ASP.NET Web API教程】4.3 ASP.NET Web API中的异常处理

参考页面: http://www.yuanjiaocheng.net/webapi/create-crud-api-1-delete.html http://www.yuanjiaocheng.net/webapi/Consume-web-api.html http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-get.html http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-po

备忘:VC++ 中的异常处理

当程序遇到一个异常或一个严重的错误时,通常意味着它不能继续正常运行并且需要停止执行.任何的设计都离不开对异常与错误的处理.如果设计者不主动规避程序异常,往往在程序发生异常时,会被系统终止而直接退出.这对使用者来说,是很不友好的. 如果主动处理异常,可以显式地提示错误地发生,也可以避免程序异常终止.更好的处理是,在设计时,预估一些错误,让用户避开这些错误以让程序顺利运行.对一些无法预知的异常,也需要我们通过VC++的异常处理机制,显式地告诉错误已发生,并保证程序的继续进行. VC++提供了两种不同