How to catch two exceptions in one stack when use using - c#

class Program
{
static void Main(string[] args)
{
try
{
using (var ss = new extest()) {
throw new Exception("Exception1");
}
}
catch(Exception ex)
{
System.Console.WriteLine(ex.Message);
}
}
}
class extest : IDisposable
{
public void Dispose()
{
throw new Exception("Exception2");
}
}
Run the codes result is "Exception2",
So I want to know how you can catch two exceptions, or just catch an Exception1.
My project has thousands of such using, which does not add try, but extest's Dispose is only one place, and I hope to know what exception has thrown before the Dispose.
Thanks

The problem in your example is that the second exception is thrown while the first exception is being handled. I.e. the using statement is effectively a try/finally pair, with the call to Dispose() in the finally block. So, the second exception supersedes the first one.
Having a Dispose() method that throws an exception is a very bad idea. So, the best solution here is to fix that. Don't throw an exception from a Dispose() method. But if you can't fix that for some reason and you want to see both, you need to make sure you're in a position to catch both. You can do this by adding another try/catch inside the using:
try
{
using (var ss = new extest()) {
try
{
throw new Exception("Exception1");
}
catch (Exception exInner)
{
System.Console.WriteLine(ex.Message);
throw;
}
}
}
catch(Exception ex)
{
System.Console.WriteLine(ex.Message);
}

The easiest way to handle this would be to rearrange your code:
static void Main(string[] args)
{
try
{
using (var ss = new extest())
{
try
{
CodeThatMightThrowAnException();
}
catch (Exception e)
{
// Process Exception here
}
}
}
catch(Exception ex)
{
System.Console.WriteLine(ex.Message);
}
}
Edit:
If the handling of the exceptions inside the using is always going to be the same, you could build a helper class that could make refactoring easier:
public class TryCatchHelper
{
public Exception Exception { get; private set; } = null;
public void Execute(Action action)
{
try
{
action()
}
catch (Exception e)
{
exception = e;
}
}
}
Then in your method:
static void Main(string[] args)
{
var helper = new TryCatchHelper();
try
{
using (var ss = new extest())
{
helper.Execute(() => {
// Your Code Block Here
});
}
}
catch(Exception ex)
{
// The Dispose threw an exception
}
if (helper.Exception != null)
{
// Handle the exception from the block here.
}
}

it's impossible to catch more than 1 exception.
when you throw Exception2 it should be catched in your catch clause. when you see "Exception2" it is printed by System.Console.WriteLine(ex.Message);. So, you can change the log in catch, or change the throwing exception message in Dispose.
reference added:
class Program
{
static void Main(string[] args)
{
try
{
using (var ss = new extest()) {
...
}
}
catch(Exception ex)
{
System.Console.WriteLine("extest error : " + ex.Message);
}
}
}
class extest : IDisposable
{
public void Dispose()
{
throw new Exception("Dispose failed: reason");
}
}

Related

How to throw and catch an exception

I fully accept that this is essentially a repeat of question of
Catching custom exception in c#
That question is closed, so I hope to rephrase it as I am having the same problem.
I have a class that can be summarised thus..
[Serializable()]
public class DataFile : ISerializable
{
public DataFile()
{
// Data structures
}
public DataFile(SerializationInfo info, StreamingContext ctxt) : this()
{
if(true)
{
throw new VersionNotFoundException();
}
// Load data
}
public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
{
// Save data
}
}
In my MainForm, I have a method that constains code equivilant to..
private DataFile Data;
private string CurrentFile = "C:\myfile.xyz";
private void LoadData()
{
try
{
using (Stream stream = File.Open(CurrentFile, FileMode.Open))
Data = (DataFile)new BinaryFormatter().Deserialize(stream);
}
catch (VersionNotFoundException e)
{
// never gets here
}
catch (Exception e)
{
// VersionNotFoundException gets caught here as an inner exception
}
}
My question(s)
Why would the VersionNotFoundException not get caught in the "catch (VersionNotFoundException e)" section (have I not added it to the top of the exception stack)? What am I doing wrong and how do I fix it? Why/how am I making an 'inner' exception and how do I stop it?
I was scratching my head with this and completely missed the comment.
// VersionNotFoundException gets caught here as an inner exception
You cannot catch inner exceptions like this, however you can use when in C#6 or later
try
{
}
catch (Exception e) when (e.InnerException is VersionNotFoundException e2)
{
Console.WriteLine(e2.Message);
}
catch (Exception e)
{
}
Demo here

Handle exceptions in events

In this example I have two subscribers to my event. One of the subscribers raises an Exception but I would like to prevent all subscribers to fail when only one of them incurs in an Exception. The try-catch statement is not enough to capture the exception of the Dog class, it makes the Cat class fails too.
using System;
namespace EventsExample
{
class BreadWinnerEventArgs : EventArgs
{
public string Name { get; set; }
}
class BreadWinner // publisher
{
public event EventHandler<BreadWinnerEventArgs> ArrivedHome; // 2.
public void Action(BreadWinnerEventArgs args)
{
Console.WriteLine("Papa says: I'm at home!");
OnArriveHome(args);
}
protected virtual void OnArriveHome(BreadWinnerEventArgs args)
{
if (ArrivedHome != null)
{
foreach (EventHandler<BreadWinnerEventArgs> handler in ArrivedHome.GetInvocationList())
{
try
{
var t = ArrivedHome; // publisher uses sames signature as the delegate
if (t != null)
t(this, args);
}
catch (Exception e)
{
Console.WriteLine("Error in the handler {0}: {1}", handler.Method.Name, e.Message);
}
}
}
}
}
class Dog
{
public void OnArrivedHome(object source, BreadWinnerEventArgs e)
{
throw new Exception();
Console.WriteLine(String.Format("Dog says: Whoof {0}!", e.Name));
}
}
class Cat
{
public void OnArrivedHome(object source, BreadWinnerEventArgs e)
{ Console.WriteLine(String.Format("Cat hides from {0}", e.Name)); }
}
class Program
{
static void Main(string[] args)
{
BreadWinner papa = new BreadWinner(); // publisher
Dog dog = new Dog(); // subscriber
Cat cat = new Cat();
papa.ArrivedHome += dog.OnArrivedHome; // subscription
papa.ArrivedHome += cat.OnArrivedHome;
papa.Action(new BreadWinnerEventArgs() { Name = "Papa" });
Console.Read();
}
}
}
You almost had it, you just where using t where you should have been using handler, you also where using ArrivedHome where you should have been using t. I also modified the code to wrap up all the exceptions and the delegate who called them in to a custom exception then wrap those in an aggragate exception and have the code raise that.
protected virtual void OnArriveHome(BreadWinnerEventArgs args)
{
var t = ArrivedHome; // publisher uses sames signature as the delegate
if (t != null)
{
var exceptions = new List<Exception>();
foreach (EventHandler<BreadWinnerEventArgs> handler in t.GetInvocationList())
{
try
{
try
{
handler(this, args);
}
catch (Exception e)
{
Console.WriteLine("Error in the handler {0}: {1}", handler.Method.Name, e.Message);
throw new DelegateException(handler, e, this, args); //Throw the exception to capture the stack trace.
}
}
catch (DelegateException e)
{
exceptions.Add(e);
}
}
if (exceptions.Count > 0)
{
throw new AggregateException(exceptions);
}
}
}
///Elsewhere
sealed class DelegateException : Exception
{
public Delegate Handler { get; }
public object[] Args { get; }
public DelegateException(Delegate handler, Exception innerException, params object[] args) : base("A delegate raised an error when called.", innerException)
{
Handler = handler;
Args = args;
}
}
However I don't think you really should be doing this, this deviates from the "expected behavior" and may catch other programmers off guard if they have to consume your classes that do this.
I'm not saying that you should do this, but this is one way to handle it:
protected virtual void OnArriveHome(BreadWinnerEventArgs args)
{
var handler = ArrivedHome;
if (handler == null)
return;
foreach (var subscriber in handler.GetInvocationList())
{
try
{
subscriber(this, args);
}
catch (Exception ex)
{
//You can, and probably should, remove the handler from the list here
}
}
}
This allows you to invoke each one of the subscribers individually instead of as a group, and catch an exception when one of them throws. The problem I have with doing this is that you really can't know what broke, or do anything to fix it. All you can do is log and optionally remove that event handler so that the next time you don't throw on that one.
Removing the handler may also be bad practice since it can be difficult to trace why a previously assigned handler is now unassigned.

How to handle all Exception in Custom Exception Class?

I want to handle all exceptions to a Custom Exception Class. I don't want to raise Custom Exception in try block I want to every exception will catch by my custom Exception Class.
I don't want to do this:
private static void Main(string[] args)
{
try
{
Console.WriteLine("Exception");
throw new CustomException("Hello World");
}
catch (CustomException ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadLine();
}
I want this:
private static void Main(string[] args)
{
try
{
Console.WriteLine("Exception");
throw new Exception("Hello World");
}
catch (CustomException ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadLine();
}
public class CustomException : Exception
{
public CustomException()
{
}
public CustomException(string message) : base(message)
{
}
public CustomException(string message, Exception innerException)
: base(message, innerException)
{
}
protected CustomException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
Hope you get my question.
You cannot change the existing Exception classes.
But you can catch the exception and convert it to a CustomException:
try
{
try
{
// Do you thing.
}
catch(Exception e)
{
throw new CustomException("I catched this: " + e.Message, e);
}
}
catch(CustomException e)
{
// Do your exception handling here.
}
I don't know it this is what you want, but I think this is the closest you can do.
I am guessing you want to achieve this, beacause you want to treat every exception as if it was a CustomException. Well, why not just treat every exception in that way? Handle every exception the way you would handle your CustomException. If there are some Exceptions that you don't want to handle as a CustomException, then what you want to achieve is not what is in you question.
If you absolutely must treat everything as a CustomException, you could do something like this;
try
{
//Something that causes any form of exception
}
catch (Exception ex)
{
throw new CustomException(ex.Message); //Caught and handled in another place.
}
However, I don't think that's a sensible approach.

Where do I handle asynchronous exceptions?

Consider the following code:
class Foo {
// boring parts omitted
private TcpClient socket;
public void Connect(){
socket.BeginConnect(Host, Port, new AsyncCallback(cbConnect), quux);
}
private void cbConnect(IAsyncResult result){
// blah
}
}
If socket throws an exception after BeginConnect returns and before cbConnect gets called, where does it pop up? Is it even allowed to throw in the background?
Code sample of exception handling for asynch delegate from msdn forum. I beleive that for TcpClient pattern will be the same.
using System;
using System.Runtime.Remoting.Messaging;
class Program {
static void Main(string[] args) {
new Program().Run();
Console.ReadLine();
}
void Run() {
Action example = new Action(threaded);
IAsyncResult ia = example.BeginInvoke(new AsyncCallback(completed), null);
// Option #1:
/*
ia.AsyncWaitHandle.WaitOne();
try {
example.EndInvoke(ia);
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
*/
}
void threaded() {
throw new ApplicationException("Kaboom");
}
void completed(IAsyncResult ar) {
// Option #2:
Action example = (ar as AsyncResult).AsyncDelegate as Action;
try {
example.EndInvoke(ar);
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
}
}
If the process of accepting a connection results in an error your cbConnect method will be called. To complete the connection though you'll need to make the following call
socket.EndConnection(result);
At that point the error in the BeginConnect process will be manifested in a thrown exception.

How to Automatically re-raise Exceptions

If you wrap a call to HttpResponse.End within a try catch block, the ThreadAbortException would automatically be re-raised. I assume this is the case even if you wrap the try catch block in a try catch block.
How can I accomplish the same thing? I do not have a real-world application for this.
namespace Program
{
class ReJoice
{
public void End() //This does not automatically re-raise the exception if caught.
{
throw new Exception();
}
}
class Program
{
static void Main(string[] args)
{
try
{
ReJoice x = new ReJoice();
x.End();
}
catch (Exception e) {}
}
}
}
You can't change ordinary exceptions to have this behaviour. ThreadAbortException has special support for this that you can't implement yourself in C#.
ThreadAbortException is a special exception that can be caught, but it will automatically be raised again at the end of the catch block.
It's as simple as using the plain throw statement.
throw;
in the relevant catch block. Note that this is advantageous over doing throw e; because it preserves the call stack at the point of the exception.
Of course, this isn't automated in perhaps the sense you want, but unfortunately that is not possible. This is pretty much the best solution you'll get, and pretty simple still I think. ThreadAbortException is special in the CLR because it is almost inherent in thread management.
In the case of your program, you'd have something like:
namespace Program
{
class ReJoice
{
public void End()
{
throw new Exception();
}
}
class Program
{
static void Main(string[] args)
{
try
{
ReJoice x = new ReJoice();
x.End();
}
catch (Exception e)
{
throw;
}
}
}
}
You mean like this?
namespace Program
{
class ReJoice
{
public void End() //This does not automatically re-raise the exception if caught.
{
throw new Exception();
}
}
class Program
{
static void Main(string[] args)
{
try
{
ReJoice x = new ReJoice();
x.End();
}
catch (Exception e) {
throw e;
}
}
}
}
Edit: It doesn't re-raise the exception because the meaning of "catch" is to handle the exception. It is up to you as the caller of x.End() what you want to do when an exception occurs. By catching the exception and doing nothing you are saying that you want to ignore the exception. Within the catch block you can display a message box, or log the error, kill the application entirely, or rethrow the error with additional information by wrapping the exception:
throw new Exception("New message", e);

Categories

Resources