【问题标题】:throw an Exception in thread C#在线程 C# 中抛出异常
【发布时间】:2011-01-23 13:06:41
【问题描述】:

我有这样的线程,在我看到示例后link text

ThreadStart _threadStart = new ThreadStart(delegate()
{
       try
       {
           threadFunction(httpContext);
       }
       catch (Exception ex)
       {
           throw ex;
       }
 });
 Thread _thread = new Thread(_threadStart);
  _thread.Start();

当异常发生时,它不会在启动它的线程中重新抛出。 那么我做错了什么或怎么做?

注意:感谢所有先进的 cmets

【问题讨论】:

  • 请注意,您应该永远像您在此处那样重新抛出异常。只需在 catch 块中执行 throw; 就足够了……
  • 我知道我会抛出从“System.Exception”继承的自定义异常并带有消息
  • 你必须抛出一个 new 异常来添加你想要添加的信息。将 original 异常作为 InnerException 传递。仅当添加的信息具有很高的价值时才这样做,因为这会使故障排除更加困难。

标签: c# multithreading


【解决方案1】:

将抛出异常,但这只会结束线程。异常不会在启动它的线程中重新抛出。

【讨论】:

  • 这是为什么呢?什么是最好的解决方案?
  • @Hiyasat:如果一个线程可以随时在它的启动线程中抛出任何异常,那么实现启动线程来处理它将非常困难。您必须像发回任何其他结果一样将异常传达回起始线程,例如使用两个线程都可以访问的变量。
【解决方案2】:

我认为问题的核心是理解线程内发生的异常不会传递给调用线程进行处理。

比如说你有一个rebel方法:

private static void RebelWithoutACause()
{
    throw new NullReferenceException("Can't touch this!");
}

假设您在程序中创建了一个调用此方法的新线程,并且作为一名安全的程序员,您决定将工作封装在 try/catch 块中:

private static void Main(string[] args)
{
    try
    {
        var thread = new Thread(RebelWithoutACause);
        thread.Start();
        thread.Join();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

但是,如果你在调试器中运行它,你会发现你永远不会到达catch 块,相反,线程将被杀死,并且调试器会抱怨你有一个未处理的异常。

您需要选择如何处理异常,但处理需要在每个线程入口方法中进行。典型的处理包括记录详细信息、通过 UI 通知用户以及尽可能优雅地关闭您的应用程序。

【讨论】:

    【解决方案3】:

    你确定抛出了异常吗?如果线程因异常而失败,整个应用程序将崩溃,您可以使用AppDomain.CurrentDomain.UnhandledException 事件注意到这一点(注意,在事件触发时,您无法阻止应用程序结束,但可以清理资源并保存关键数据 - 请参阅事件文档了解更多信息)。

    但是,从您提到的线程中引用accepted answer

    任何引发顶级异常的线程都表明存在大问题。

    您应该尝试记录异常,和/或向其他线程发出此线程已失败的信号。

    【讨论】:

      【解决方案4】:

      异常被抛出,但我猜你看不到它,因为它是在另一个线程上抛出的。因此,UI 线程(或调用其他线程的任何线程)无法捕获异常,因为它看不到它。

      例如,如果您将异常记录到文件中,我相信您会看到它。 :)

      【讨论】:

      • 异常将出现在它引发的任何线程上。我认为根本没有例外 - 线程刚刚正常完成。
      • 我确信发生了异常,但它不会被抛出到主线程
      【解决方案5】:

      我认为也许您应该考虑使用 BackgroundWorker 类。您可以订阅 RunWorkerCompleted 事件,它有一个 Error 属性,将包含您的异常。

      【讨论】:

      【解决方案6】:

      也许可以这样做:

         const int numThreads = 8;
         Thread[] threads = new Thread[numThreads];
         Exception[] threadsExceptions = new Exception[numThreads];
         for (int i = 0; i < numThreads; i++) {
             threadsExceptions[i] = null;
             int closureVariableValue = i;
             ThreadStart command = () =>
             {
                 try
                 {
                     throw new ArgumentException("thread_" + closureVariableValue + "'s exception");
                 }catch(Exception any)
                 {
                     threadsExceptions[closureVariableValue] = any;
                 }
             };
             threads[i] = new Thread(command);
             threads[i].Start();
         }
         for(int i = 0; i < numThreads; i++)
         {
             threads[i].Join();
             if (threadsExceptions[i] != null)
             {
                 throw threadsExceptions[i];
             }
         }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-01-06
        • 1970-01-01
        • 2018-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-16
        • 1970-01-01
        相关资源
        最近更新 更多