This question already has answers here:
What is the best way to catch exception in Task?
(2 answers)
Catching Error when using Task.Factory
(5 answers)
Closed 5 years ago.
I'm trying to catch a "nested" or "encapsulated" custom error (I504Error) in my code. I know this normally isn't best practice, but it should work for my use case as the error is very specific. I'm trying to get the try/catch block to catch the I504Error in my Main method but it doesn't catch it, even though it's getting called from inside the try/catch block. My program just stops where I'm throwing the error. What am I doing wrong here?
// Custom Error Handler
public class I504Error : Exception
{
public I504Error()
{
}
}
// Classes
public abstract class AbstractIternetThing
{
public abstract void DoSomething();
}
public class IternetThing : AbstractIternetThing
{
public override void DoSomething()
{
// bunch of other stuff
if (iternetThingWorkedProperly == false)
{
// Program stops here, doesn't get caught by the try/catch block in Program.Main()
throw new I504Error();
}
}
}
// Main script
class Pogram
{
static void Main(string[] args)
{
List<Task<AbstractIternetThing>> programThreads = new List<Task<AbstractIternetThing>>();
IternetThing iThing = new IternetThing();
try
{
for (int wantedThread = 0; wantedThread < 5; wantedThread++)
{
Task<AbstractIternetThing> iThingTask = new Task<AbstractIternetThing>(() => iThing.DoSomething());
iThingTask.Start();
}
}
// The Error should get caught here, but it doesnt?
catch (I504Error)
{
// Do something else
}
}
}
It is because you have it in a Task which is on a separate asynchronous execution path. Consider using async-await. Then the compiler will rewrite your code to make it work as you expect.
Related
I have not come across any Question/Solution in Stackoverflow for this question which has got some high number of votes.
So I thought I will ask it again here.
How to handle or what to do if there is an Exception in Dispose() method.
Shall we Log it or if I Rethrow the Exception, will it get Rethrown. I might want to Rethrow it so that I come to know I made a mistake somewhere in my Dispose()
Even If we suppose it does get Rethrown, will it be a good practice to rethrow it?
In most (but not all) cases, your exception handlers should be at the code entry point.
Just let the exception bubble up, like this.
public static class Program
{
public static void Main()
{
try
{
using (new QuestionableCodeAtBest()) {}
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
}
class QuestionableCodeAtBest : IDisposable
{
const int TotalHands = 2;
public void Dispose()
{
var handsThatAreClapping = 0;
Console.WriteLine($"What is the sound of no hands clapping?: {TotalHands / handsThatAreClapping}");
}
}
This question already has answers here:
The variable 'MyException' is declared but never used
(6 answers)
Closed 6 years ago.
I need to clear this warning :
try
{
// doSomething();
}
catch (AmbiguousMatchException MyException)
{
// doSomethingElse();
}
The compiler is telling me : The variable 'My Exception' is declared but never used
How can I fix this.
Try this one,
try
{
doSomething()
}
catch (AmbiguousMatchException)
{
doSomethingElse()
}
If you are not going to use the exception details, you can use the try like this:
try
{
doSomething();
}
catch // all types of exceptions will caught here
// if you need to deal with particular type of exceptions then specify them like
// catch (AmbiguousMatchException)
{
doSomethingElse();
}
Or else you have to use the variable for something like the following:
try
{
doSomething();
}
catch (AmbiguousMatchException MyException)
{
WriteToLog(MyException.ToString());
// doSomethingElse();
}
where WriteToLog method will be defined as like the following:
public static void WriteToLog(string exceptionDetails) {
// write the details to a file/DB
}
[I understand that there are 100's of similar question on the net but I am still not able to find out a working solution to this problem and hence posting it.]
I have a c# Win-Form application. The application is used for downloading images via FTP from another server.
With the help of a task scheduler, the application runs 3 times a day and downloads the images and after that it closes automatically.
It used to work fine last year, however, since the beginning of this year, we are getting unhandled exception like "request timed out" or "operation timed out" from the application.
Thus instead of the application getting closed automatically, it shows a windows dialog with "continue" and "quit" button.
My requirement is that the application should close automatically in case any unhandled exception is thrown.
I have written the following code in my program.cs to handle this. However, this is also not working and I am still getting exceptions window.
[STAThread]
static void Main()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
static void MyHandler(object sender, UnhandledExceptionEventArgs args)
{
System.Diagnostics.Process proc = System.Diagnostics.Process.GetCurrentProcess();
System.Windows.Forms.Application.Exit();
System.Environment.Exit(0);
proc.Kill();
return;
}
There are several events to which you may need to subscribe to ensure that you catch EVERY possible exception:
Application.ThreadException += yourThreadExceptionHandler;
AppDomain.CurrentDomain.UnhandledException += yourUnhandledExceptionHandler;
TaskScheduler.UnobservedTaskException += yourUnobservedTaskExceptionHandler;
And of course you should also have a try/catch around the body of the program:
public static void Main()
{
try
{
runProgram();
}
catch (Exception exception)
{
// Your main exception handler.
}
}
You can have a common exception handling mechanism that all your attached handlers call, to avoid duplicated code. UnobservedTaskException might be something you want to handle differently (log it and otherwise ignore, perhaps).
Dealing with unhandled exceptions is a pain, and usually leads to a loss of context, making it very hard to know what to do next. There are ways of dealing with this gracefully though.
As it happens, I wrote a blog post on the subject just today. This extends the usual exception handling to give you a more robust and predictable execution path.
The way it works is that you wrap any potentially failing parts of the code in something that will catch any exceptions, and wrap them up in a way that you can deal with them. I did this by having an abstract Fallible class that has three inherited classes, Success, Failure and BadIdea. There is a helper method that does this for you, leaving you with an object that either contains the data you want, or an exception that you can use to log the error, report to the user, etc.
The abstract class looks like this...
public abstract class Fallible<T> {
public static Fallible<T> Do(Func<T> f) {
Fallible<T> result;
try {
T fResult = f();
result = new Success<T> {Value = fResult};
}
catch (BadIdeaException ex) {
result = new BadIdea<T> {Exception = ex};
}
catch (Exception ex) {
// NOTE that in a real application, we would log the exception at this point
result = new Failure<T> {Exception = ex};
}
return result;
}
public void Match(Action<T> onSuccess, Action<Exception> onFailure,
Action<Exception> onBadIdea = null) {
switch (this) {
case Success<T> success:
onSuccess(success.Value);
break;
case BadIdea<T> badIdea:
if (onBadIdea != null) {
onBadIdea(badIdea.Exception);
} else {
onFailure(badIdea.Exception);
}
break;
case Failure<T> failure:
onFailure(failure.Exception);
break;
}
}
}
You then create inherited classes like this...
public abstract class Fallible<T> {
}
public class Success<T> : Fallible<T> {
public T Value { get; set; }
}
public class Failure<T> : Fallible<T> {
public Exception Exception { get; set; }
}
You can then wrap your potentially failing calls in the Do() method, and handle what happens afterwards...
var c = Fallible<Customer>.Do(() => CustomerBll.GetCustomer(id));
c.Match(
c => Customer = c,
e => AlertUser(ex)
);
The first lambda passed to Match tells it what to do in case of success, and the second tells it what to do in case of failure.
This enables you to handle your exceptions much more gracefully. See the blog post for more details.
This avoids the need for a global exception handler.
I have the following code:
[Serializable]
class ExceptionAspectHandler:OnExceptionAspect
{
public override void OnException(MethodExecutionArgs args)
{
Console.WriteLine("{0}", args.Exception);
args.FlowBehavior = FlowBehavior.Continue;
}
}
[OnExceptionAspect]
public static void divide()
{
int n = Convert.ToInt32(Console.ReadLine());
var a = 100 / n; //the exception happens here
Console.WriteLine("it should get here");
}
Using FlowBehavior.Continue ends divide() and returns to the main() method.
Remember, the OnException aspect wraps your code in a try/catch so the code will continue from the catch (instead of rethrowing) and it's behavior will default to return. Are you wanting it to continue from where it threw the exception? If so, you need to explicitly wrap that line in a try/catch yourself.
Please read http://www.sharpcrafters.com/blog/post/Day-6-Your-code-after-PostSharp.aspx for more details.
The attribute used in divide() method should be ExceptionAspectHandler (you've created), not OnExceptionAspect.
I am trying to get the list of calls made from the beginning of a try block to the exception. In the code below, when I fall into the Catch block, the StackTrace in the Exception object is the following :
at ConsoleApplication.Program.MethodC() / at
ConsoleApplication.Program.Main(String[] args).
This is totally expected, but doesn't help me to get the history of calls. Does anybody have an idea on how I could do this?
static void MethodA() { }
static void MethodB() { }
static void MethodC() { throw new Exception(); }
static void Main(string[] args)
{
try
{
MethodA();
MethodB();
MethodC();
}
catch (Exception e)
{
// Get list of calls
throw;
}
}
I was surprised to see that the StackTrace property of the Exception object isn't StackTrace object. Is there any reason for this?
In the end, the purpose of all this is simple. If an exception is thrown during the execution of the code, I want to look at the meta data (attribute) of each of the methods called.
As I understand your question, you want to be able to know which methods was called before MethodC in your try block. I don't think you can do that without adding code to your methods.
When MethodA finishes executing, it is no longer on the stack, so there is nowhere you can get the information from. Same goes for MethodB, and only MethodC is on the stack when the Exception occurs.
It seems you're not going to be able to get a stack trace for each method called with the try block unless you add custom logging code to each method. However, you can create a System.Diagnostics.StackTrace option easily from an exception simply by passing the Exception object to the constructor. This will make available all the information about the stack trace including whether the exception was thrown from MethodA/MethodB/MethodC, which might be at least somewhat helpful to you.
Example code:
static void MethodA() { }
static void MethodB() { }
static void MethodC() { throw new Exception(); }
static void Main(string[] args)
{
try
{
MethodA();
MethodB();
MethodC();
}
catch (Exception e)
{
System.Diagnostics.StackTrace callStack = new System.Diagnostics.StackTrace(e);
System.Diagnostics.StackFrame frame = null;
System.Reflection.MethodBase calledMethod = null;
System.Reflection.ParameterInfo[] passedParams = null;
for (int x = 0; x < callStack.FrameCount; x++)
{
callStack.GetFrame(x);
calledMethod = frame.GetMethod();
passedParams = calledMethod.GetParameters();
foreach (System.Reflection.ParameterInfo param in passedParams)
System.Console.WriteLine(param.ToString());
}
}
}
(You can see this SO thread for the original answer containing the code. I've just slightly modified it.)
Hope that's at least a partial solution to your question.
You can easily get a StackTrace object from anywhere in your code but as has already been pointed out you can not get the full history of method calls.