The MessageBox.Show call below shows "Inner". Is this a bug?
private void Throw()
{
Invoke(new Action(() =>
{
throw new Exception("Outer", new Exception("Inner"));
}));
}
private void button1_Click(object sender, EventArgs e)
{
try
{
Throw();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message); // Shows "Inner"
}
}
I had a look at the reference source for System.Windows.Forms.Control, and the code that deals with Invoke looks like this:
try {
InvokeMarshaledCallback(current);
}
catch (Exception t) {
current.exception = t.GetBaseException();
}
GetBaseException:
public virtual Exception GetBaseException()
{
Exception inner = InnerException;
Exception back = this;
while (inner != null) {
back = inner;
inner = inner.InnerException;
}
return back;
}
So apparently it's like this by design. The comments in the source offer no explanation as to why they do this.
EDIT: Some site that is now gone claims this comment came from a guy at Microsoft:
Based on the winform comfirmation in the record, our analysis is
correct of the root cause and this behavior is intended. The reason was to
prevent the user from seeing too much of the Windows.Forms internal mechanisms.
This is because the winform's default error dialog also leverages Application.ThreadException to show the exception details. .Net Winform
team trims the other exceptions information so that the default error
dialog will not display all the details to the end user.
Also, some MSFTs have sugguested to change this behavior. However, .Net
Winform team thinks that changing the exception to throw is a breaking
change and for this reason WinForms will keep sending the innermost exception to the Application.ThreadException handler.
The OP doesn't seem to be interested in a work-around. Anyhow, this is mine:
public static object InvokeCorrectly(this Control control, Delegate method, params object[] args) {
Exception failure = null;
var result = control.Invoke(new Func<object>(() => {
try {
return method.DynamicInvoke(args);
} catch (TargetInvocationException ex) {
failure = ex.InnerException;
return default;
}
}));
if (failure != null) {
throw failure;
}
return result;
}
Related
I am wondering can try..catch force execution to go into the catch and run code in there?
here example code:
try {
if (AnyConditionTrue) {
// run some code
}
else {
// go catch
}
} catch (Exception) {
// run some code here...
}
try{
if (AnyConditionTrue){
//run some code
}
else{
throw new Exception();
}
}
catch(){
//run some code here...
}
But like Yuck has stated, I wouldn't recommend this. You should take a step back at your design and what you're looking to accomplish. There's a better way to do it (i.e. with normal conditional flow, instead of exception handling).
Rather than throwing an Exception in the else, I would recommend extracting the code from your catch into a method and call that from your else
try
{
if (AnyConditionTrue)
{
MethodWhenTrue();
}
else
{
HandleError();
}
}
catch(Exception ex)
{
HandleError();
}
Yes, you have to throw exception :
try
{
throw new Exception("hello");
}
catch (Exception)
{
//run some code here...
}
An effective way to throw an Exception and also jump to Catch as so:
try
{
throw new Exception("Exception Message");
}
catch (Exception e)
{
// after the throw, you will land here
}
if(conditiontrue)
{
}
else{
throw new Exception();
}
Yes, if you throw the exception that you intend to catch from within the try, it will be caught in the catch section.
I have to ask you why you would want to do this though? Exception handling is not meant to be a substitute for control flow.
I think what you want is a finally block: http://msdn.microsoft.com/en-us/library/zwc8s4fz(v=vs.80).aspx
see this
try
{
doSomething();
}
catch
{
catchSomething();
throw an error
}
finally
{
alwaysDoThis();
}
This is different if/when you do this:
try
{
doSomething();
}
catch
{
catchSomething();
throw an error
}
alwaysDoThis();// will not run on error (in the catch) condition
the the this last instance, if an error occurs, the catch will execute but NOT the alwaysDoThis();. Of course you can still have multiple catch as always.
As cadrel said, but pass through an Exception to provide more feedback, which will be shown in the innerException:
try
{
if (AnyConditionTrue)
{
MethodWhenTrue();
}
else
{
HandleError(new Exception("AnyCondition is not true"));
}
}
catch (Exception ex)
{
HandleError(ex);
}
...
private void HandleError(Exception ex) {
throw new ApplicationException("Failure!", ex);
}
public class CustomException: Exception
{
public CustomException(string message)
: base(message) { }
}
//
if(something == anything)
{
throw new CustomException(" custom text message");
}
you can try this
You could throw an exception to force a catch
throw new Exception(...);
why are you catching an exception? Why not just run the code in your "else" block? If you MUST do it that way, just throw a new exception
throw new Exception();
Slight resurrection, but I wanted to add both a sample (primarily like others) and a use case.
public int GetValueNum(string name)
{
int _ret = 0;
try
{
Control c = (extendedControls.Single(s => s.ValueName == name) as Control);
if (c.GetType() == typeof(ExtendedNumericUpDown))
_ret = (int)((ExtendedNumericUpDown)c).Value;
else
throw new Exception();
}
catch
{
throw new InvalidCastException(String.Format("Invalid cast fetching .Value value for {0}.\nExtendedControllerListener.GetValueNum()", name));
}
return _ret;
}
In my case, I have custom controls - a handful of controls that use a base Windows.Forms control, but add two bools and a string for tracking, and also automatically get registered to a Singleton List<T> so they can be properly fetched without drilling down through control containers (it's a tabbed form).
In this case, I'm creating some methods to easily get values (.Value, .Text, .Checked, .Enabled) by a name string. In the case of .Value, not all Control objects have it. If the extended control is not of type ExtendedNumericUpDown, it IS an InvalidCastException as the method should not be called against that type of control. This isn't flow, but the prescribed usage of invalid cast. Since Control doesn't naturally have a .Value property, Visual Studio won't let me just force an attempt and fail after.
I have following problem. I want to catch exception as shown below, instead I get NullReferenceException. Is there a way to catch the exception thrown inside of this Anonymous method ?
SynchronizationContext _debug_curr_ui = SynchronizationContext.Current;
_debug_curr_ui.Send(new SendOrPostCallback(delegate(object state) {
throw new Exception("RESONANCE CASCADE: GG-3883 hazardous material failure");
}),null);
I would appreciate any help.
You could still use try/catch inside your anonymous method:
_debug_curr_ui.Send(new SendOrPostCallback(delegate(object state) {
try
{
throw new Exception("RESONANCE CASCADE: GG-3883 hazardous material failure");
}
catch (Exception ex)
{
// TODO: do something useful with the exception
}
}), null);
As an alternative you could modify this Send method and catch the exception just before invoking the delegate:
public void Send(SendOrPostCallback del)
{
// ...
try
{
del();
}
catch (Exception ex)
{
// TODO: do something useful with the exception
}
// ...
}
I suspect that you are getting the NullReferenceException because _debug_curr_ui is null.
Otherwise you should be able to wrap the code that you posted in a try/catch block and catch the excpetion. You should also think about using ApplicationException and not Exception.
try
{
Action someMethod = delegate() { throw new ApplicationException("RESONANCE CASCADE: GG-3883 hazardous material failure"); };
someMethod();
}
catch
{
Console.WriteLine("ex caught");
}
MSDN ApplicationException
If I understand correctly, you want the anonymous delegate to throw the exception, and you want to catch this exception somewhere outside of the anonymous delegate.
In order to answer that, we will need to know what you are actually doing with the delegate, and how it is being invoked. Or, to be more specific, what does the _debug_curr_ui.Send method do with the delegate?
something like below
delegate(object obj)
{
try
{
}
catch(Exception ex)
{
}
}
When C# throws an exception, it can have an inner exception. What I want to do is get the inner-most exception, or in other words, the leaf exception that doesn't have an inner exception. I can do this in a while loop:
while (e.InnerException != null)
{
e = e.InnerException;
}
But I was wondering if there was some one-liner I could use to do this instead.
Oneliner :)
while (e.InnerException != null) e = e.InnerException;
Obviously, you can't make it any simpler.
As said in this answer by Glenn McElhoe, it's the only reliable way.
I believe Exception.GetBaseException() does the same thing as these solutions.
Caveat: From various comments we've figured out it doesn't always literally do the same thing, and in some cases the recursive/iterating solution will get you further. It is usually the innermost exception, which is disappointingly inconsistent, thanks to certain types of Exceptions that override the default. However if you catch specific types of exceptions and make reasonably sure they're not oddballs (like AggregateException) then I would expect it gets the legitimate innermost/earliest exception.
Looping through InnerExceptions is the only reliable way.
If the caught exception is an AggregateException, then GetBaseException() returns only the innermost AggregateException.
http://msdn.microsoft.com/en-us/library/system.aggregateexception.getbaseexception.aspx
If you don't know how deep the inner exceptions are nested, there is no way around a loop or recursion.
Of course, you can define an extension method that abstracts this away:
public static class ExceptionExtensions
{
public static Exception GetInnermostException(this Exception e)
{
if (e == null)
{
throw new ArgumentNullException("e");
}
while (e.InnerException != null)
{
e = e.InnerException;
}
return e;
}
}
I know this is an old post, but I'm surprised nobody suggested GetBaseException() which is a method on the Exception class:
catch (Exception x)
{
var baseException = x.GetBaseException();
}
This has been around since .NET 1.1. Documentation here:
http://msdn.microsoft.com/en-us/library/system.exception.getbaseexception(v=vs.71).aspx
Sometimes you might have many inner exceptions (many bubbled exceptions).
In which case you might want to do:
List<Exception> es = new List<Exception>();
while(e.InnerException != null)
{
es.add(e.InnerException);
e = e.InnerException
}
You could use recursion to create a method in a utility class somewhere.
public Exception GetFirstException(Exception ex)
{
if(ex.InnerException == null) { return ex; } // end case
else { return GetFirstException(ex.InnerException); } // recurse
}
Use:
try
{
// some code here
}
catch (Exception ex)
{
Exception baseException = GetFirstException(ex);
}
The extension method suggested (good idea #dtb)
public static Exception GetFirstException(this Exception ex)
{
if(ex.InnerException == null) { return ex; } // end case
else { return GetFirstException(ex.InnerException); } // recurse
}
Use:
try
{
// some code here
}
catch (Exception ex)
{
Exception baseException = ex.GetFirstException();
}
Not quite one line but close:
Func<Exception, Exception> last = null;
last = e => e.InnerException == null ? e : last(e.InnerException);
In fact is so simple, you could use Exception.GetBaseException()
Try
//Your code
Catch ex As Exception
MessageBox.Show(ex.GetBaseException().Message, My.Settings.MsgBoxTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
End Try
You have to loop, and having to loop, it's cleaner to move the loop into a separate function.
I created an extension method to deal with this. It returns a list of all of the inner exceptions of the specified type, chasing down Exception.InnerException and AggregateException.InnerExceptions.
In my particular problem, chasing down the inner exceptions was more complicated than usual, because the exceptions were being thrown by the constructors of classes that were being invoked through reflection. The exception we were catching had an InnerException of type TargetInvocationException, and the exceptions we actually needed to look at were buried deep in the tree.
public static class ExceptionExtensions
{
public static IEnumerable<T> innerExceptions<T>(this Exception ex)
where T : Exception
{
var rVal = new List<T>();
Action<Exception> lambda = null;
lambda = (x) =>
{
var xt = x as T;
if (xt != null)
rVal.Add(xt);
if (x.InnerException != null)
lambda(x.InnerException);
var ax = x as AggregateException;
if (ax != null)
{
foreach (var aix in ax.InnerExceptions)
lambda(aix);
}
};
lambda(ex);
return rVal;
}
}
Usage is pretty simple. If, for example, you want to know if we encountered a
catch (Exception ex)
{
var myExes = ex.innerExceptions<MyException>();
if (myExes.Any(x => x.Message.StartsWith("Encountered my specific error")))
{
// ...
}
}
I ran into this and wanted to be able to list all of the exception messages from the exception "stack". So, I came up with this.
public static string GetExceptionMessages(Exception ex)
{
if (ex.InnerException is null)
return ex.Message;
else return $"{ex.Message}\n{GetExceptionMessages(ex.InnerException)}";
}
Another way you could do it is by calling GetBaseException() twice:
Exception innermostException = e.GetBaseException().GetBaseException();
This works because if it is an AggregateException, the first call gets you to the innermost non-AggregateException then the second call gets you to the innermost exception of that exception. If the first exception is not an AggregateException, then the second call just returns the same exception.
How is it possible to resume code execution after an exception is thrown?
For example, take the following code:
namespace ConsoleApplication1
{
public class Test
{
public void s()
{
throw new NotSupportedException();
string #class = "" ;
Console.WriteLine(#class);
Console.ReadLine();
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
}
catch (Exception ex)
{
}
}
}
}
After catching the exception when stepping through, the program will stop running. How can I still carry on execution?
EDIT: What I specifically mean is the line Console.WriteLine(#class); does not seem to be hit, because when I run to it when in debug mode, the program exits from debug mode. I want to run to this line and stop at it.
Thanks
Well, you don't have any code after the catch blocks, so the program would stop running. Not sure what you're trying to do.
The following should be proof that the program doesn't simply "stop" after the catch blocks. It will execute code after the catch blocks if there is code to be executed:
static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
Console.WriteLine("ArgumentException caught!");
}
catch (Exception ex)
{
Console.WriteLine("Exception caught!");
}
Console.WriteLine("I am some code that's running after the exception!");
}
The code will print the appropriate string depending on the exception that was caught. Then, it will print I am some code that's running after the exception! at the end.
UPDATE
In your edit you asked why Console.WriteLine(#class); does not seem to be hit. The reason is that you are explicitly throwing an exception in the very first line of your s() method; anything that follows is ignored. When an exception is encountered, execution stops and the exception is propagated up the call stack until the appropriate handler can handle it (this may be a catch block that corresponds to the try that wraps the statement in question within the same method, or it may be a catch block further up the call-stack. If no appropriate handler is found, the program will terminate with a stacktrace [at least in Java - not sure if the same happens in C#]).
If you want to hit the Console.WriteLine line, then you shouldn't be explicitly throwing an exception at the beginning of the method.
It sounds like you're wanting resumeable exceptions. C# doesn't do resumeable exceptions, and I'm doubtful that CLR supports them.
The purpose of throwing an exception is to abort a function and an entire operation (call stack) if/when something in the call environment (parameters, object state, global state) makes the function's operation impossible or invalid. Passing a zero param to a function that needs to divide a quantity by that param, for example. Division by zero won't produce a meaningful result, and if that's the sole purpose of the function, then the function can't return a meaningful result either. So, throw an exception. This will cause execution to jump to the nearest catch or finally block on the call stack. There is no returning to the function that threw the exception.
If you want to step into your code in the debugger to trace the Console.WriteLine() calls, you need to remove the throw new NotSupportedException() line from your code and recompile.
If you're worried that an exception will be thrown in the method but you want the method to continue, add an error handler inside the method.
class Test
{
public void s()
{
try
{
// Code that may throw an exception
throw new NotSupportedException();
}
catch(Exception ex)
{
// Handle the exception - log?, reset some values?
}
string #class = "" ;
Console.WriteLine(#class);
Console.ReadLine();
}
}
You could also return a bool or some other value to indicate the state.
Disclaimer: I am not suggesting that you actually do this.
You can mimic the old VB style On Error Resume Next with the following code.
public static class ControlFlow
{
public static Exception ResumeOnError(Action action)
{
try
{
action();
return null;
}
catch (Exception caught)
{
return caught;
}
}
}
And then it could be used like the following.
public static void Main()
{
ControlFlow.ResumeOnError(() => { throw new NotSupportedException(); });
ControlFlow.ResumeOnError(() => { Console.WriteLine(); });
ControlFlow.ResumeOnError(() => { Console.ReadLine(); });
}
Some simple code I put together to catch exceptions that are thrown inside a catch block:
try
{
//do code here
}
catch (Exception ex)
{
try { SomeMethod1(); }
catch { }
try { SomeMethod2(); }
catch { }
try { SomeMethod3(); }
catch { }
}
finally
{
//cleanup goes here
}
Execution is still carying on but there is no code after the exception is caught. If you want to repeatedly call s then consider wrapping the try/catch block in a while loop.
The program stops running because there is no following code to be executed in the Main() method! You can add the following line to your code to keep the program running until there is a console input:
Console.ReadLine();
For that code, you can't. If you break the tasks up to smaller chunks, you can resume at the next chunk. But normally it's easier to have a different mechanism than exceptions to report non-fatal errors, such as a callback function which returns whether or not to continue.
You can use the "step-over" feature in debugging to achieve this on a per-run basis.
Instead of thowing the NotSupportedException, you could track that an exception was encountered, use a default value, and throw the exception at the end of the method call:
namespace ConsoleApplication1
{
public class Test
{
public void s()
{
bool exceptionEncountered = false;
if(someConditionNotSupported){//stub condition
exceptionEncountered=true
#class="DefaultValue";
}
Console.WriteLine(#class);
Console.ReadLine();
if(exceptionEncountered){
throw new NotSupportedException();
}
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
}
catch (Exception ex)
{
}
}
}
}
public static void Main()
{
for (int j = 0; j <= 100000; j++)
{
try
{
// TODO: Application logic...
}
catch
{
System.Threading.Thread.Sleep(1000);
}
}
}
I'm trying to write some code that catches a particular exception and throw a more useful one for something higher up the call stack to deal with but also catch more general exceptions and handle them.
The code is something like this:
try
{
// Do stuff
}
catch (SomeException e)
{
throw new SomeExceptionWithContextInfo();
}
catch (Exception e)
{
// Handle unexpected exception gracefully
}
The problem I'm having is that the general exception is catching my new exception. is there a way to avoid this?
My current solution involves checking the type of the exception and throwing it again if it's type is what I just created.
The code you've posted should work, as shown in this test app:
using System;
class OtherException : Exception {}
class Test
{
static void Main(string[] args)
{
try
{
Foo();
}
catch (OtherException)
{
Console.WriteLine("Caught OtherException");
}
}
static void Foo()
{
try
{
string x = null;
int y = x.Length;
}
catch (NullReferenceException)
{
throw new OtherException();
}
catch (Exception)
{
Console.WriteLine("Caught plain Exception");
}
}
}
This just prints "Caught OtherException" not "Caught plain Exception". Are you sure you don't have a nested try block in your real code? Could you post a short but complete example which shows your problem?
Do you really need to catch Exception in your method though? That's very rarely a good idea.
You're doing it right. The general exception will not catch the specific one.
The code you posted is the way to do it (catch for more specific exception must appear first).
I suggest looking again at the code, as either they are not in that order, or the code isn't actually throwing that exception type.
Here is a link on msdn about try-catch: http://msdn.microsoft.com/en-us/library/0yd65esw(VS.80).aspx
Don't catch general exceptions might be the answer? Find out which Exceptions that can be thrown and catch them separately.
try { // Outer try/catch
DoSomething();
try {
/* */
} catch(NotGeneralException e) {
/* */
} catch(AnotherNotGeneralException e) {
throw new SomeOtherException("Exception message");
}
} catch(SomeOtherException e) {
/* */
}
Alternatively only catch a general exception and rethrow SomeOtherExcepion
try {
} catch(Exception e) {
throw new SomeOtherException("Exception message");
}