C# 在线程C中引发异常#

C# 在线程C中引发异常#,c#,multithreading,C#,Multithreading,在我看到示例后,我有这样的线程 当异常发生时,它不会被抛出启动它的线程。 那么我做错了什么或者怎么做 注意:由于advanced中的所有注释,正在抛出异常,除非我猜您没有看到它,因为它是在另一个线程上抛出的。因此,UI线程(或调用其他线程的任何线程)无法捕获异常,因为它没有看到异常 例如,如果您将异常记录到一个文件中,我相信您会看到它。:) 将抛出异常,但这只会结束线程。异常不会在启动它的线程中重新引发。是否确实引发了异常?如果某个线程因异常而失败,则整个应用程序将崩溃,您可以通过使用事件注意到

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

当异常发生时,它不会被抛出启动它的线程。 那么我做错了什么或者怎么做


注意:由于advanced中的所有注释,正在抛出异常,除非我猜您没有看到它,因为它是在另一个线程上抛出的。因此,UI线程(或调用其他线程的任何线程)无法捕获异常,因为它没有看到异常


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

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

是否确实引发了异常?如果某个线程因异常而失败,则整个应用程序将崩溃,您可以通过使用事件注意到这一点(请注意,在触发事件时,您无法阻止应用程序结束,但可以清理资源并保存关键数据-有关详细信息,请参阅事件文档)

但是,引用您提到的线程:

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


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

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

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

例如,假设您有一个叛逆方法:

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
块,相反,线程将被终止,调试器将抱怨您有未处理的异常


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

可以这样做:

   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];
       }
   }
const int numThreads=8;
线程[]线程=新线程[numThreads];
异常[]线程ceptions=新异常[numThreads];
for(int i=0;i
{
尝试
{
抛出新的ArgumentException(“thread_”+closureVariableValue+”的异常);
}捕获(任何异常)
{
threadsExceptions[closureVariableValue]=任何;
}
};
线程[i]=新线程(命令);
线程[i].Start();
}
for(int i=0;i
注意,您不应该像在那里那样重复出现异常。只是做
扔就足够了…我知道我会抛出从“System.exception”继承的自定义异常,其中包含message您必须抛出一个新异常,其中包含要添加的信息。将原始异常作为InnerException传递。仅当添加的信息具有高价值时才执行此操作,因为这会增加故障排除的难度。无论引发什么线程,都会看到异常。我认为根本没有异常-线程刚刚正常完成。我确信会发生异常,但它不会抛出到主线程。为什么?那么最好的解决方案是什么?@Hiyasat:如果一个线程可以在任何时候在它的起始线程中抛出任何异常,那么要实现起始线程来处理它将非常困难。您必须将异常传回起始线程,就像传回任何其他结果一样,例如使用两个线程都可以访问的变量。谢谢,但我在.NET 4任务中发现了更强大的功能。谢谢链接-任务看起来很棒,我还没有机会检查它们。
   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];
       }
   }