Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么C中的主线程不处理线程池线程上引发的异常#_C# - Fatal编程技术网

C# 为什么C中的主线程不处理线程池线程上引发的异常#

C# 为什么C中的主线程不处理线程池线程上引发的异常#,c#,C#,我有以下代码片段 class Program { static void Main(string[] args) { try { Thread m_thread = new Thread(() => { //try //{ checkexc();

我有以下代码片段

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Thread m_thread = new Thread(() =>
                {
                    //try
                    //{
                        checkexc();
                    //}
                    //catch (Exception ex)
                    //{

                    //}
                }
                );               
            m_thread.Start();

        }
        catch (Exception ex)
        {

        }
    }
    static void checkexc()
    {
        throw new NullReferenceException();
    }
}

覆盖的Try-Catch块不处理NullReferenceException。但是,如果我将委托包装在thread()构造函数中,那么它将由Try Catch处理。为什么不尝试捕获处理此异常。

因为异常没有发生在线程构造函数中。只有在调用m_thread.Start()并在另一个线程上执行后,才会调用checkexc()

想象你有一条主路(a),另一条路从那条路(B)分出

当一辆卡车沿着a行驶时,如果它撞车了,a就会知道,交通就会停止

当一辆卡车沿着B行驶时,如果它撞车了,B就会知道,交通就会停止

但是B通过什么机制告诉A一辆卡车撞到了它

一旦卡车在B上,它不会影响A,除非沿A有另一个进入B的入口点

其他线程中的异常将如何与主线程通信?一旦另一个线程运行,它就不再(直接)与主线程通信。

正如其他人所说,“因为它位于不同的线程中”。或者换一种说法,为什么第一个线程会因为另一个线程出现异常而受到困扰


如果使用
BackgroundWorker
,则异常会在
RunWorkerCompleted
事件的参数中传递出去(线程完成时)-因此,根据您的情况,这可能会更简单。

从另一个角度回答此问题:

任务并行库(TPL)确实为您处理(捕获和传播)异常

但是异常出现在等待()任务完成的点,而不是开始任务的点/线程

    // No point in specifically surrounding the next 2 statements
    Task t1 = Task.Factory.StartNew(() => Foo());
    Task t2 = Task.Factory.StartNew(() => Bar());

    try
    {
        Task.WaitAll(t1, t2);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);  // Aggregated exceptions from Foo and/or Bar
    }

使用
Parallel.ForEach()
时,代码看起来像您的代码,因为ForEach()的末尾有一个隐式的WaitAll()

正如Matt的详细解释,在子线程上抛出的异常不会出现在父线程上。但是,如果您希望能够从子线程捕获异常,有一种方法:

class Program {
    static void Main(string[] args) {
        Action action = BeginCheckExc;
        IAsyncResult result = action.BeginInvoke(new AsyncCallback(EndCheckExc), null);

        try {
            action.EndInvoke(result);
        }
        catch (Exception ex) { // Exception is caught here
            Console.WriteLine(ex.Message);
        }
    }

    static void BeginCheckExc() {
        Thread.Sleep(3000); // Simulate long operation
        throw new Exception("Oops! Something broke!");
    }

    static void EndCheckExc(IAsyncResult result) {
        Console.WriteLine("Done");
        Console.ReadLine();
    }
}
您将看到的输出类似于:

完成了

哎呀!有东西坏了

按任意键继续


如果您对从所有线程捕获未处理的异常感兴趣,可以添加应用程序范围的未处理异常处理程序。请查看&&

基本上,您需要处理的代码是:

Application.ThreadException += new ThreadExceptionEventHandler(ThreadExceptionFunction);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionFunction);

public static void ThreadExceptionFunction(object sender, ThreadExceptionEventArgs args)
{
     // Handle the exception.          
}

public static void UnhandledExceptionFunction(object sender, UnhandledExceptionEventArgs args)
{
     // Handle the exception. 
}

请记住,异常发生后,应用程序可能处于损坏状态,因此最好在记录错误后尽快退出。

因为它是另一个线程。是的,这是一个泄漏的抽象