次の方法で共有


Why you can't catch some exceptions

If you've been using .NET (or any previous exception-based languages like JScript or C++) for a while then you are probably used to doing something like this:

try

{

  someObject.MethodThatMightFail()

}

catch
(ex)

{

  print("uh, something went wrong")

}

But this doesn't always work, especially when you are writing a library that is called by some code you don't own. Kind of like a VSTO project. The times it doesn't work are when using MethodThatMightFail fails at JIT-time (Just In Time compilation) rather than at run-time. For example, if the assembly containing the type that implements the method can't be loaded, the JITter can't JIT the method in which case your try-catch block will never even execute; instead, the method that called your method will receive an exception (probably a MethodInvocationException or a FileNotFoundException or something similar, possibly with an InnerException containing the reason for failure).

If the calling method is not owned by you -- eg, it is an event handler where the caller is Word or Excel in the VSTO case -- they will receive the exception and will most likely throw it away. Therefore if you want to call a method that may fail for some drastic reason such as the assembly not being installed or a LinkDemand failing, then you should wrap it in your own function:

try

{

  Helper()

}

catch
(ex)

{

  print("uh, something went wrong")

}

 

// Meanwhile, in another part of the code...

 

function
Helper()

{

someObject.MethodThatMightFail()

}

This is a common problem with the _Startup or Open methods in VSTO projects where customers call into assemblies that either are in the wrong directory or are not trusted, and the problem goes unreported by the host app.

Comments

  • Anonymous
    February 07, 2004
    Oh and you can't catch EngineExecutionExceptions either, because that means the CLR itself died (usually due to an AV inside an unmanaged portion of the runtime).
  • Anonymous
    February 07, 2004
    Since when can't you catch EE exceptions? I know a number of these wound up in the Terrarium Watson logs. The Watson code was 100% managed and was able to catch these in very rare situations.

    I don't know if we've seen any of these post V1/V1.1, but I do know that we got them back in "the day". There is probably a historical marker somewhere showing the change from what I saw, and what you are seeing now.
  • Anonymous
    February 07, 2004
    I consider this a bug in the CLR or at the very least an undesirable feature ;-)

    I think your helper trick is fragile, because inlining might cause the same thing to happen.

    IMHO, what the CLR should do in such cases is emit code that throws the exception at the point where it matters (so in this case it would emit code to throw an exception instead of the method call). That way the system behaves consistently and more obvious.
  • Anonymous
    February 07, 2004
    One EE exception is the following

    try {
    System.Runtime.InteropServices.GCHandle h = (System.Runtime.InteropServices.GCHandle)(new IntPtr(12));
    } catch {
    Console.WriteLine( "Never" );
    }

    It's compatible with 1.0 and 1.1, I dont know if 2.0 has the same behavior or introduces a breaking change<g>