System.Reflection.TargetInitationException 未被捕获

2024-03-29

解决方案后添加的注释:在反射调用的方法中抛出了 AccessViolationException。这就是无法捕获 TargetInitationException 的原因。

注意:这是在 IDE 外部。引用的问题不相同。 https://stackoverflow.com/questions/2658908/why-is-targetinvocationexception-treated-as-uncaught-by-the-ide

TL;DR

  1. 无法获取堆栈跟踪
  2. 无法获取内部异常
  3. 无法使用调试器(第三方库的复制保护方案妨碍)
  4. 对代码的任何更改都会阻止异常发生 - 意味着我无法添加日志记录来找出异常发生的位置

我怎样才能捕获异常或以其他方式获取所需的信息?

详细描述:

我遇到了由反射调用的方法中发生的异常问题。异常本身实际上发生在被调用的方法中,但由于该方法是通过反射调用的,因此真正的异常被包装在System.Reflection.TargetInvocationException。没问题,只需捕获它并获取内部异常 - 除了System.Reflection.TargetInvocationException不会被抓住。我的程序崩溃了,我得到了一个转储以及 Windows 事件日志中的一个条目。

Windows 事件日志不包含内部异常,转储也不包含。 我无法将调试器附加到程序中,因为这样外部库(需要进行反射调用)将无法运行 - 复制保护,你不知道吗? 如果我将 try/catch 放入有问题的方法中,则不会发生异常 - 这很糟糕。原因尚未解决,只是不再发生。 如果我将日志记录到有问题的方法中,也会发生相同的效果 - 异常不再发生。

我无法使用日志记录,无法使用调试器,并且在我可以捕获异常并记录它的地方,异常不会被捕获。

我正在使用 Visual Studio 2010 和 dotnet 4.0。

明确地说:当程序在 Visual Studio 外部运行时,try/catch 不起作用,并且我无法在调试器中的 Visual Studio 内部运行它,因为这样程序就无法到达异常点发生。这不在 IDE 内。

消除反射不是一种选择(我只针对一种情况尝试过,并且异常消失了。)

被调用的方法做了很多事情,但是将其分解为更小的方法并没有帮助 - 异常就消失了。

异常不会一直发生,只有当我执行特定的步骤序列时才会发生 - 并且当它发生时,它总是在整个序列中第二次发生。

在我使用的序列中,该方法几乎同时被两个线程调用 - 输入一组特定的数据,这会导致在两台单独的打印机上打印一份报告和另一个文档的副本 - 每台打印机一个报告和一个文档。由于生成报告和打印文档可能需要一段时间,因此它们是在后台线程上完成的,以便用户可以继续工作。

我怀疑这些线程互相干扰(正在进行大量文件和数据库操作),但不知道到底发生了什么,我无法修复它。

下面的代码显示了反射调用的简化版本。

有没有人对可能导致这一问题的原因提出建议System.Reflection.TargetInvocationException不被捕获,或者也许是捕获内部异常的替代方法?

Try
    Dim methode As System.Reflection.MethodInfo
    methode = GetType(AParticularClass).GetMethod("OneOfManyMethods", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Static)
    Dim resultobject As Object = methode.Invoke(Nothing, Reflection.BindingFlags.InvokeMethod Or Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Static, Nothing, New Object() {SomeBooleanVariable, SomeStringVariable},  Nothing)
    result = DirectCast(resultobject, DataSet)
Catch ex As Exception
    'Log the error here.
End Try

找到了无法捕获异常的原因:

实际的异常是 AccessViolationException,如果不采取特殊步骤,就无法在 dotnet 4.0 中捕获该异常(如何处理 AccessViolationException。 https://stackoverflow.com/questions/3469368/how-to-handle-accessviolationexception)

为了让事情变得更有趣,当在通过反射调用的方法中抛出 AccessViolationException 时,Windows 事件日志中只会记录 TargetInvocableException,并且转储中也只有 TargetInitationException 可用。

当我设法获得真正的异常时,我发现是从非 GUI 线程调用 Application.DoEvents() 导致了 AccessViolation。在 GUI 线程上调用 DoEvents() 可以带来足够的乐趣(使用Application.DoEvents() https://stackoverflow.com/questions/5181777/use-of-application-doevents),更不用说从后台线程调用时了。

一旦修复了这个问题,我发现我们的第三方库(具有复制保护的库)不喜欢在单独的实例中同时调用。解决这个问题需要在正确的位置设置同步锁。

引起所有这些乐趣的代码一度都在 GUI 线程中,并且最初是在 dotnet 1.1 时代编写的 - 这解释了对 DoEvents 的调用。代码已被分段转换为通过几个不同的阶段在后台线程中并行运行,没有任何一个开发人员能够完整地了解该过程。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

System.Reflection.TargetInitationException 未被捕获 的相关文章

随机推荐