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

  • 相关阅读:
    手速太慢QAQ
    最短路总结
    放下
    素材收集
    NOI2018旅游记
    -5
    七月
    德国GG了
    本人自传
    bzoj2369
  • 原文地址:https://www.cnblogs.com/fdyang/p/5081058.html
Copyright © 2011-2022 走看看