Code sample:
using System;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
Console.WriteLine("Start");
Foo f = new Foo();
f.FooAsync();
}
public class Foo
{
public async void FooAsync()
{
try
{
await Task.Run(() =>
{
Console.WriteLine("Throwing");
throw new Exception();
});
}
catch (Exception)
{
Console.WriteLine("Caught");
}
}
}
}
The above code when run from C# fiddle or from the console on my PC prints:
Start
Throwing
Caught
C# Fiddle Example
However, when I run it from Visual Studio (F5 in debug mode), I get the following message:
I don't understand why I get "was not handled in user code" message from Visual Studio although running it from the console or C# fiddle is fine. Am I missing something obvious?
UPDATE
I've tried waiting on the task f.FooAsync().Wait(); in Main, but the exception is still reported as being unhandled (same error message).
First, what's special about this exception is that it's being thrown from Task.Run and for that scope, the exception really isn't handled by user-code.
The framework catches and stores the exception in the returned task for you to handle later, if you fail to do that it's an unobserved task exception (which in .Net 4.0 would've crashed the application).
The issue here is the "Enable Just My Code" feature in the settings. When the feature is turned on the debugger breaks on exceptions when you leave user-code and enter framework-code and at that point the exception really wasn't handled.
If you turn that feature off the debugger will not break on that exception as it will follow your code into the framework and see the exception being handled and stored in the task. The exception will then be re-thrown when you await the task and be handled by your code.
Since the handling that actually matters is the one being done by the framework, this is an even simpler example:
public static void Main()
{
Task.Run(() =>
{
throw new Exception();
});
Console.ReadLine();
}
With "Enable Just My Code" turned on the debugger will break on the exception, without it the debugger will not.
Related
I run into troubles using the Roslyn Scripting Engine. I get no exception handling when I run a script within a delegation.
Test that works as expected:
string script = #"var a=0; var b=2/a;";
var runner = CSharpScript.Create<object>(script);
var errors = runner.Compile();
Assert.IsTrue(errors.IsEmpty);
try
{
runner.RunAsync();
Assert.Fail("Where is the exception");
}
catch (System.Exception)
{
// everything is OK! Error thrown...
}
Result: No Assertion. The Exception was thrown.
Here's the text using a delegate object:
Unittest:
string script = #"var a=0; var b=2/a;";
var runner = CSharpScript.Create<object>(script);
var errors = runner.Compile();
var delegat = runner.CreateDelegate();
Assert.IsTrue(errors.IsEmpty);
try
{
delegat();
Assert.Fail("Where is the exception?");
}
catch (System.DivideByZeroException)
{
// everything is OK! Error thrown...
}
I got the fail message and no exception was thrown.
We cache the delegates to speed up the compilation and during a test we see that runtime exceptions are not thrown. So I wrote the test to reproduce this situation.
I can't find any hint in the docs which describes that there are no exceptions thrown during the invoke.
Can someone give me a pointer or a hint why this happens?
There are two issues with your code:
In the first version, you're catching Exception, which means that when the Assert.Fail is reached and throws AssertionException, that exception is then caught and ignored.
This means that there is no difference between RunAsync and delegate here, neither of them throws DivideByZeroException.
Both RunAsync and the ScriptRunner<T> delegate return Task. That means to actually wait for them to complete or to observe any exceptions, you need to use await. Once you do that, you will see the DivideByZeroException that you're expecting.
Your Main finishes execution before the scheduler gets a chance to invoke delegat. It is a task that will run asynchronously. You can see that when you inspect it in the debugger:
To force execution inside the scope of the try...catch, you can use this:
try
{
delegat().Wait();
}
catch(System.AggregateException ex)
{
/* the inner exception of ex will be your DivideByZeroException */
}
The correct type of exception to expect in this case is the AggregateException, see here why.
A solution with await is also possible:
await delegat();
but this will compile only when the containing method can be marked async which is not necessarily what you want (show more of the calling code to clarify).
I have created the following C# program:
namespace dispose_test
{
class Program
{
static void Main(string[] args)
{
using (var disp = new MyDisposable())
{
throw new Exception("Boom");
}
}
}
public class MyDisposable : IDisposable
{
public void Dispose()
{
Console.WriteLine("Disposed");
}
}
}
When I run this using dotnet run, I see the following behavior:
Windows: Exception text written to console, "Disposed" printed ~20 second later, program exits.
Linux: Exception text written to console, program exits immediately. "Disposed" never written.
The delay on Windows is annoying, but the fact that Dispose() isn't called at all on Linux is troubling. Is this expected behavior?
EDITS Clarifications/additions from the conversation below:
This is not specific to using/Dispose(), which is just a special case of try/finally. The behavior also occurs generally with try/finally - the finally block is not run. I have updated the title to reflect this.
I have also checked for the execution of Dispose() by writing a file to the filesystem, just to ensure that problem wasn't related to stdout being disconnected from the console before Dispose() is run in the case of an unhandled exception. Behavior was the same.
Dispose() does get called if the exception is caught anywhere within the application. It's when it goes completely unhandled by the application that this behavior occurs.
On Windows, the long gap is not due to compilation delay. I started timing when the exception text was written to the console.
My original experiment was doing dotnet run on both platforms, which means separate compilations, but I have also tried by doing dotnet publish on Windows and directly running the output on both platforms, with the same result. The only difference is that, when run directly on Linux, the text "Aborted (core dumped)" is written after the exception text.
Version details:
dotnet --version -> 1.0.4.
Compiling to netcoreapp1.1, running on .NET Core 1.1.
lsb-release -d -> Ubuntu 16.04.1 LTS
Official response is that this is an expected behavior.
Interestingly enough, the C# doc page on try-finally explicitly calls this out right at the top (emphasis mine)
Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up. For more information, see Unhandled Exception Processing in the CLR.
Usually, when an unhandled exception ends an application, whether or not the finally block is run is not important. However, if you have statements in a finally block that must be run even in that situation, one solution is to add a catch block to the try-finally statement. Alternatively, you can catch the exception that might be thrown in the try block of a try-finally statement higher up the call stack. That is, you can catch the exception in the method that calls the method that contains the try-finally statement, or in the method that calls that method, or in any method in the call stack. If the exception is not caught, execution of the finally block depends on whether the operating system chooses to trigger an exception unwind operation.
One thing I found in my experimentation is that it doesn't appear to be enough to catch the exception, you have to handle it as well. If execution leaves the catch block via a throw, the finally will not run.
If you surround this with a try-catch, the finally block will run when the exception is caught (handled) by the outer catch.
static void Main(string[] args)
{
try
{
using (var disp = new MyDisposable())
{
throw new Exception("Boom");
}
}
catch (Exception e)
{
throw;
}
}
I am sure I am doinig something wrong, but when I try this example of the new threading task exception handling I keep getting the exception unhandled by user code. The whole point of the code is to show an example of how to catch errors in tasks.
Link: Task Exception Example
static void Main(string[] args)
{
var task1 = Task.Factory.StartNew(() =>
{
throw new MyCustomException("I'm bad, but not too bad!");
});
try
{
task1.Wait();
}
catch (AggregateException ae)
{
// Assume we know what's going on with this particular exception.
// Rethrow anything else. AggregateException.Handle provides
// another way to express this. See later example.
foreach (var e in ae.InnerExceptions)
{
if (e is MyCustomException)
{
Console.WriteLine(e.Message);
}
else
{
throw;
}
}
}
}
Most likely user error just not sure what (Using Visual Studio 2012);
From the page you cited:
Note
When "Just My Code" is enabled, Visual Studio in some cases will
break on the line that throws the exception and display an error
message that says "exception not handled by user code." This error is
benign. You can press F5 to continue and see the exception-handling
behavior that is demonstrated in these examples. To prevent Visual
Studio from breaking on the first error, just uncheck the "Just My
Code" checkbox under Tools, Options, Debugging, General.
I have some strange problem here. Exception thrown by Task always not handled independently how can I try to handle it.
I try this:
http://msdn.microsoft.com/en-us/library/dd997415%28v=vs.110%29.aspx
private class MyCustomException : Exception
{
public MyCustomException(String message) : base(message)
{
}
}
public static void Main()
{
var task1 = Task.Factory.StartNew(() =>
{
throw new MyCustomException("I'm bad, but not too bad!");
});
try
{
task1.Wait();
}
catch (AggregateException ae)
{
// Assume we know what's going on with this particular exception.
// Rethrow anything else. AggregateException.Handle provides
// another way to express this. See later example.
foreach (var e in ae.InnerExceptions)
{
if (e is MyCustomException)
{
Console.WriteLine(e.Message);
}
else
{
throw;
}
}
}
Console.Read();
}
this:
http://dotnetcodr.com/2014/02/11/exception-handling-in-the-net-task-parallel-library-with-c-the-basics/
this:
http://blogs.msdn.com/b/pfxteam/archive/2010/08/06/10046819.aspx
this:
var task = Task.Factory.StartNew(() => this.InitializeViewModel(myViewModel));
task.ContinueWith(o => MyErrorHandler(task.Exception), TaskContinuationOptions.OnlyOnFaulted);
and check a lot of other similar questions on StackOverflow. But It is always the same - exception is not handled. It is not handled on these primitive code snippets! I think it is some magic here...
I work on .Net Framework 4.0
Meanwhile single way to handle exception that works for me is:
Task.Factory.StartNew(() =>
{
try
{
//do something that thrown exception
}
catch (Exception)
{
}
});
If you run that example code in Visual Studio, you will indeed get the message MyCustomException was unhandled by user code and Visual Studio will break in that line.
That does not mean that your exception is really unhandled. It just means that, by default, Visual Studio breaks on exceptions which are not handled inside the Task. You can verify this by running your application without debugging (Ctrl-F5); you will note that your exception gets handled as expected.
This issue is described in more detail in the following SO question:
Stop visual studio from breaking on exception in Tasks
Microsoft Visual Studio debugging facilities for managed code have an option "Just My Code". This option enabled forces debugger to break in immediately when an exception leaves user code (Task delegate in your example) and enters non-user code (TPL internal in your example). This feature was designed before introduction of TPL to make .NET applications debugging more comfortable with looking only at the code you have written and ignore other code, such as system calls. Just My Code hides non-user code so that it does not appear in the debugger windows. When you step, the debugger steps through any non-user code but does not stop in it.
But now in fact "Just My Code" feature interfere with TPL implementation.
There are four ways to deal with this issue:
Run your code without debugging.
Just ignoring of the Visual Studio debugger message about unhanded exception by continuation of program execution.
Disabling of "Just My Code" option in the Microsoft Visual Studio. This variant is recommended by Microsoft guy Danny Shih from Parallel Computing Platform team (PFX Team) http://blogs.msdn.com/b/pfxteam/archive/2010/01/11/faq-the-debugger-does-not-correctly-handle-task-exceptions.aspx.
When calling a method via methodInfo.Invoke, if an exception is thrown it does not seem to propagate up to my catch blocks.
object value;
try
{
value = myMethod.Invoke(null, parameters);//program crashes with uncaught exception
}
catch
{
throw new Exception("Caught!");//never executed
}
The particular exception this method is raising is KeyNotFoundException, but that shouldn't matter because I'm catching everything right?
The particular error message I get from Visual Studio is
KeyNotFoundException was unhandled by user code
whereas normally the message would say
KeyNotFoundException was unhandled
if the call was not a reflected invocation.
I could just have the method check to see if they key is in there, and if not return null, but Using exception handling seems preferable. Is there any way to propagate exceptions up from a reflected method call?
This could be an issue with the Visual Studio debugger as well. As noted in the accepted answer to this similar question here, there are a few workarounds that you can do. The simplest of which is changing your Visual Studio debugger to turn off "Just My Code" in Tools -> Options -> Debugging -> General. You can also wrap it in a delegate or explicitly try to catch the invocation exception and inspect the inner exception of that, which should be your KeyNotFoundException.
It works for me:
using System;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
var method = typeof(Program).GetMethod("ThrowException");
try
{
method.Invoke(null, null);
}
catch (TargetInvocationException e)
{
Console.WriteLine("Caught exception: {0}", e.InnerException);
}
}
public static void ThrowException()
{
throw new Exception("Bang!");
}
}
Note that you do need to catch TargetInvocationException which is the exception thrown directly by Method.Invoke, wrapping the exception thrown by the method itself.
Can you come up with a similar short but complete program which demonstrates the problem?
If an error occurs during a method invoked with reflection, it should throw a TargetInvocationException that wraps (via .InnerException) the original. There are, however, a few methods that could cause more terminal fails, such as a few methods around winform creation / the message loop.
It is also possible that the method is working, but is causing additional work to happen on another thread, and it is that that is failing. This would kill the thread, and you can't catch it as it isn't on your thread. This would be particularly likely if your code is actually on a worker thread.