代码之家  ›  专栏  ›  技术社区  ›  Maksym Gontar

MS考试70-536-如何抛出和处理线程异常?

  •  2
  • Maksym Gontar  · 技术社区  · 16 年前

    在 MS Exam 70-536 .Net Foundation ,第1课创建线程中的第7章“线程”有一段文字:

    注意,因为workWithParameter方法接受一个对象thread.start 可以用任何对象而不是它期望的字符串调用。谨慎选择 线程处理未知类型的起始方法对于 线程代码。它不是盲目地将方法参数投射到字符串中,而是 测试对象类型的更好实践,如以下示例所示:

    ' VB
    Dim info As String = o as String
    If info Is Nothing Then
        Throw InvalidProgramException("Parameter for thread must be a string")
    End If
    // C#
    string info = o as string;
    if (info == null)
    {
        throw InvalidProgramException("Parameter for thread must be a string");
    } 
    

    所以,我已经试过了,但是异常处理不正确(没有控制台异常条目,程序被终止),我的代码(下面)有什么问题?

    class Program
        {
            static void Main(string[] args)
            {
                Thread thread = new Thread(SomeWork);
                try
                {
                    thread.Start(null);
                    thread.Join();
                }
                catch (InvalidProgramException ex)
                {
                    Console.WriteLine(ex.Message);
                }
                finally
                {
    
                    Console.ReadKey();
                }
            }
    
            private static void SomeWork(Object o)
            {
                String value = (String)o;
                if (value == null)
                {
                    throw new InvalidProgramException("Parameter for "+
                        "thread must be a string");
                }
            }
        }
    

    谢谢你的时间!

    5 回复  |  直到 12 年前
        1
  •  3
  •   Andrey    16 年前

    首先在VS中以调试模式启动。以下是几个问题:

        catch (InvalidProgramException ex)
        {
            Console.WriteLine(ex.Message);
        }
    

    将永远不会执行,因为异常是线程的本地异常。如果在派生线程中引发异常,其他线程将看不到它。

    throw new InvalidProgramException("Parameter for "+
                        "thread must be a string");
    

    这一行导致未处理的异常,因为在该线程中没有人捕获它。未处理的异常使整个应用程序失败。

        String value = (String)o;
        if (value == null)
    

    o可以为空,这是字符串的有效值,如果o不是字符串,则代码将引发异常。你是说:

        String value = o as String;
        if (value == null)
    
        2
  •  7
  •   Community Mohan Dere    9 年前

    中的异常处理程序 Main 方法运行的线程与引发异常的线程不同。所以,在 thread 不能陷入 主要的 . 检查 here 用于讨论为什么不希望跨线程抛出/捕获异常。你应该做的是使用一个对象来包装你的线程逻辑,但是支持异常。例如。:

    class Program
    {
        static void Main(string[] args)
        {
            ExceptionHandlingThreadWrapper wrapper = new ExceptionHandlingThreadWrapper();
            Thread thread = new Thread(wrapper.Run);
            try
            {
                thread.Start(null);
                thread.Join();
                if (wrapper.Exception != null)
                    throw new Exception("Caught exception", wrapper.Exception);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally { Console.ReadKey(); }
        }
    }
    
    public class ExceptionHandlingThreadWrapper
    {
        public ExceptionHandlingThreadWrapper()
        {
            this.Exception = null;
        }
    
        public Exception Exception { get; set; }
    
        public void Run(Object obj)
        {
            try
            {
                String value = obj as String;
                if (value == null)
                    throw new Exception("Argument must be string");
            }
            catch (Exception ex)
            {
                this.Exception = ex;
            }
        }
    }
    
        3
  •  1
  •   Otávio Décio    16 年前

    异常不会遍历线程,它只会关闭正在执行的代码。换句话说,您永远不会捕获在单独线程上引发的异常。

        4
  •  1
  •   Dathan    12 年前

    后台线程上未处理的异常将终止应用程序。这是.NET2.0中的行为变化。如果不希望应用程序在出现这种情况时死掉,则应将代码包装为 try catch 并记录该异常:

    private static void SomeWork(Object o)
    {
        try
        {
            // execution here
        }
        catch (Exception ex)
        {
            Logger.Log(ex);
        }
    }
    
        5
  •  0
  •   Randal    16 年前

    您是否考虑过使用begininvoke和endinvoke而不是创建自己的线程?这将允许捕获异常并将其带回调用方法。

    class Program
    {
        private delegate void WorkDelegate(Object o);
    
        static void Main(string[] args)
        {
            WorkDelegate workDel = new WorkDelegate(SomeWork);
            // first argument is passing a null object that will throw 
            // the exception in the SomeWork method
            IAsyncResult result = workDel.BeginInvoke(null, null, null);
            try
            {
                workDel.EndInvoke(result);
            }
            catch (InvalidProgramException ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                Console.ReadKey();
            }
        }
    
        private static void SomeWork(Object o)
        {
            String value = o as String;
            if (value == null)
            {
                throw new InvalidProgramException("Parameter for "+
                    "thread must be a string");
            }
        }
    }
    
    推荐文章