Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.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# 在另一个线程中引发异常时未调用UnhandledException_C#_Exception_.net 4.0_Clr - Fatal编程技术网

C# 在另一个线程中引发异常时未调用UnhandledException

C# 在另一个线程中引发异常时未调用UnhandledException,c#,exception,.net-4.0,clr,C#,Exception,.net 4.0,Clr,根据Microsoft文档,当线程(来自线程池或使用System.Threading.thread类创建)上发生未经处理的异常时,应用程序的默认AppDomain应触发AppDomain.UnhandledException事件。以下是MSDN,它在第二个注释部分之后进行了解释 但我无法重现这种行为,从我的测试应用程序可以看出,它从未在默认AppDomain或用于创建线程的AppDomain上触发未处理的异常。文档错误还是我的测试代码错误 using System; using System.R

根据Microsoft文档,当线程(来自线程池或使用System.Threading.thread类创建)上发生未经处理的异常时,应用程序的默认AppDomain应触发AppDomain.UnhandledException事件。以下是MSDN,它在第二个注释部分之后进行了解释

但我无法重现这种行为,从我的测试应用程序可以看出,它从未在默认AppDomain或用于创建线程的AppDomain上触发未处理的异常。文档错误还是我的测试代码错误

using System;
using System.Runtime.ExceptionServices;
using System.Reflection;

public class Program
{
    static void Main()
    {
        Program.HookAppDomainExceptions();
        Test t = CreateTestInsideAppDomain("Nested1");
        t.SetupNested1();
        Console.ReadLine();
    }

    public static Test CreateTestInsideAppDomain(string appDomainName)
    {
        AppDomain nested1 = AppDomain.CreateDomain(appDomainName);
        string executingName = Assembly.GetExecutingAssembly().FullName;
        return (Test)nested1.CreateInstanceAndUnwrap(executingName, "Test");
    }

    public static void HookAppDomainExceptions()
    {
        AppDomain.CurrentDomain.FirstChanceException +=
            new EventHandler<FirstChanceExceptionEventArgs>(FirstChanceException);

        AppDomain.CurrentDomain.UnhandledException +=
            new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
    }

    public static void FirstChanceException(object sender, FirstChanceExceptionEventArgs e)
    {
        Console.WriteLine("Domain:{0} FirstChanceException Handler",
                          AppDomain.CurrentDomain.FriendlyName);
    }

    public static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Console.WriteLine("Domain:{0} UnhandledException Handler",
                          AppDomain.CurrentDomain.FriendlyName);
    }
}

public class Test : MarshalByRefObject
{
    private delegate void Nothing();

    public void SetupNested1()
    {
        var start = new Nothing(Nested1ThreadStart);
        start.BeginInvoke(null, null);
    }

    static void Nested1ThreadStart()
    {
        Program.HookAppDomainExceptions();
        Test t = Program.CreateTestInsideAppDomain("Nested2");
        t.SetupNested2();
    }

    public void SetupNested2()
    {
        Program.HookAppDomainExceptions();
        Test t = Program.CreateTestInsideAppDomain("Nested3");
        t.ThrowException();
    }

    public void ThrowException()
    {
        Program.HookAppDomainExceptions();
        throw new ApplicationException("Raise Exception");
    }
}
使用系统;
使用System.Runtime.ExceptionServices;
运用系统反思;
公共课程
{
静态void Main()
{
Program.HookAppDomainExceptions();
Test t=CreateTestInsideAppDomain(“Nested1”);
t、 SetupNested1();
Console.ReadLine();
}
公共静态测试CreateTestInsideAppDomain(字符串appDomainName)
{
AppDomain nested1=AppDomain.CreateDomain(appDomainName);
字符串executingName=Assembly.GetExecutingGassembly().FullName;
return(Test)nested1.CreateInstanceAndUnwrap(executingName,“Test”);
}
公共静态void HookAppDomainExceptions()
{
AppDomain.CurrentDomain.FirstChanceException+=
新事件处理程序(FirstChanceException);
AppDomain.CurrentDomain.UnhandledException+=
新的未处理ExceptionEventHandler(CurrentDomain_UnhandledException);
}
公共静态无效FirstChanceException(对象发送方,FirstChanceExceptionEventArgs e)
{
WriteLine(“域:{0}FirstChanceException处理程序”,
AppDomain.CurrentDomain.FriendlyName);
}
public static void CurrentDomain_UnhandledException(对象发送方,UnhandledExceptionEventArgs e)
{
WriteLine(“域:{0}未处理的异常处理程序”,
AppDomain.CurrentDomain.FriendlyName);
}
}
公共类测试:MarshalByRefObject
{
private delegate void Nothing();
公共void SetupNested1()
{
var start=newnothing(Nested1ThreadStart);
start.BeginInvoke(null,null);
}
静态void Nested1ThreadStart()
{
Program.HookAppDomainExceptions();
Test t=Program.CreateTestInsideAppDomain(“Nested2”);
t、 SetupNested2();
}
公共void SetupNested2()
{
Program.HookAppDomainExceptions();
Test t=Program.CreateTestInsideAppDomain(“Nested3”);
t、 ThroweException();
}
公共void throweexception()
{
Program.HookAppDomainExceptions();
抛出新的ApplicationException(“引发异常”);
}
}

在您的代码中
未处理的异常
不会在任何
AppDomain
上触发,因为如果您使用
BeginInvoke()
调用委托,则会处理其执行期间引发的任何异常,然后在调用
EndInvoke()
时重新调用,而您不会这样做

如果调用
EndInvoke()

或同步执行委托:

start();
您会得到类似的结果:
main域的UnhandledException

相反,如果您按照文档中的说明操作,并使用
thread
类启动一个新线程:

new Thread(Nested1ThreadStart).Start();
已引发
Nested1
未处理异常
,并引发主应用程序域


因此,回答您的问题:文档是正确的。你的代码错了。当您使用
BeginInvoke()
异步调用委托时,您应该始终稍后调用
EndInvoke()

我也遇到了这个问题。我使用了观察者模式来解决这个问题。 您可以在调用者类中实现一个接口,该接口具有一个方法,在发生异常时从另一个线程调用该方法


这里有一个链接显示了如何实现此模式

,这不是问题的核心所在。如果OP想要(或能够)处理异常,他(可能)知道如何处理异常。问题是未处理的异常会发生什么情况。我宁愿选择
start.BeginInvoke(iar=>start.EndInvoke(iar),null)
,因为您的使用使方法调用同步。否则,回答就太好了@乔纳森,是的,这也行,但它改变了行为。它在用于调用
start
的线程上调用
EndInvoke()
,这意味着在
Nested1
(和主域)上引发
UnhandledException
。@svick-EndInvoke(BeginInvoke)没有意义,除非创建一个自然异步的方法的同步版本。@Jonathan,在实际应用程序中,没有。但这并不是实际的应用程序,它只是用来计算
未处理异常
的行为的代码。非常好的答案,正是我想要的!谢谢
new Thread(Nested1ThreadStart).Start();