zoukankan      html  css  js  c++  java
  • (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

  • 相关阅读:
    XML(学习笔记)
    css样式学习笔记
    Request(对象)
    sql一些错误修改的总结
    转载(如何学习C#)
    sql server(学习笔记2 W3Cschool)
    sql sqrver(学习笔记1 W3Cschool)
    关于 flutter开发碰到的各种问题,有的已经解决有的一直没解决或者用其他方法替代
    关于 Flutter IOS build It appears that your application still contains the default signing identifier.
    关于 flutter本地化问题 The getter 'pasteButtonLabel' was called on null
  • 原文地址:https://www.cnblogs.com/fdyang/p/5081058.html
Copyright © 2011-2022 走看看