Catching Exceptions of a Task that spawns an inner task - c#

Given the following simplified code
/// <summary>
/// Within the VS2010 debugger, the following test will cease with an
/// "Exception was unhandled by user code".
/// (Debug window reports a "A first chance exception of type
/// 'System.Exception' ..." BEFORE the exception is caught
/// further down in the execution path.)
/// OUTSIDE the VS2010 debugger, the exception is caught by the tComplete
/// task that follows the tOpen task, just as expected.
/// </summary>
public void StartToOpen_Simple()
{
Task tOpen = Task.Factory.StartNew(() => {
//do some work before spawning another task here
try
{
return Task.Factory.StartNew(() => {
Thread.Sleep(2000);
//First chance exception occurs here:
throw new Exception("Some generic exception");
}, TaskCreationOptions.AttachedToParent);
} catch (Exception ex)
{
//never fires
var source = new TaskCompletionSource<object>();
source.TrySetException(ex);
return source.Task;
}
}).Unwrap();
Task tComplete = tOpen.ContinueWith(t => {
if (t.Exception != null)
{
Exception LastOpenException = t.Exception.Flatten().GetBaseException();
if (LastOpenException is OperationCanceledException)
{
Console.WriteLine("OperationCanceledEx: " + LastOpenException.Message);
} else
{
Console.WriteLine("Some exception occured in the tOpen task, but we're prepared for it here in the tComplete task.");
Console.WriteLine("The exception message was: {0}", LastOpenException.Message);
}
} else
{
//do something if no exception occured (doesn't happen in this example)
}
}, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent, TaskScheduler.Default);
}
and testing it for example via
static void Main(string[] args)
{
AsyncTest test = new AsyncTest();
test.StartToOpen_Simple();
Console.WriteLine("Started async task. Waiting for exception");
Console.ReadKey();
}
I observe a very annoying issue while running it in the VS2010 debugger: Just like the "Summary" states, the debugger breaks at the throw in the 'tOpen' task believing that I didn't catch the exception (which i do "further below" in the 'tComplete' task). Only if I continue the debugging session do I see that the exception is "bubbled up" and hence handled as desired. If this method were run on a regular time interval (which it is!) debugging this becomes a nightmare, because the debugger breaks on each interval.
Running the program on a console, doesn't exhibit this behavior.
Can someone explain to me why the Debugger breaks at this line, i.e. it doesn't see
What are my options of being able to reasonably debug code inside VS2010 where such code exists?

First chance exception messages most often do not mean there is a problem in the code. For applications / components which handle exceptions gracefully, first chance exception messages let the developer know that an exceptional situation was encountered and was handled.
Please refer this

Related

(AccessViolationException was unhandled) How do i implement HandleProcessCorruptedStateExceptions in C#?

I came across a problem that is the AccessViolationException was unhandled after i run my program for about a day long.
(More information: I am using Visual Studio 2010)
However, it does not state where this exception occurs, there were two options given to me which is "ok" and "continue". When i pressed ok, nothing happened so i pressed continue and the program stops debugging.
When i tried to find a solution, i understand that i can implement HandleProcessCorruptedStateExceptions to fix this problem. However, i have no clue where to start.
Do i simply include the codes below only? And where do i include these code?
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
public static int Main()
{
try
{
// Catch any exceptions leaking out of the program CallMainProgramLoop();
}
catch (Exception e)
// We could be catching anything here
{
// The exception we caught could have been a program error
// or something much more serious. Regardless, we know that
// something is not right. We'll just output the exception
// and exit with an error. We won't try to do any work when
// the program or process is in an unknown state!
System.Console.WriteLine(e.Message);
return 1;
}
return 0;
}
Alternatively, i can also do this legacyCorruptedStateExceptionsPolicy but it says that i should input the required statement in the config file. Where can i find the config file?
Appreciate all the replies!
The actual answer for you question is here and I really shouldn't answer it again, but I want to show you some code sample and I don't want to write it in comment :)
In one of my projects from time to time there was an unpredictable exception. To catch it I write this code in Program.cs:
[STAThread]
static void Main()
{
// add UnhandledException handler
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e)
{
// prepare message for user
var message = "There was an unknown exception while running <app_name>!";
var exception = e.ExceptionObject as Exception;
if (exception != null)
{
// change message if there was actual exception
message = $"There was an {exception.GetType().Name} exception while running <app_name>! {exception.Message}";
// adding inner exceptions messages
var innerException = exception.InnerException;
while (innerException != null)
{
message += $"\r\n-> {innerException.GetType().Name}: {innerException.Message}";
innerException = innerException.InnerException;
}
#if DEBUG
// add tracing info
message += $"\r\n\r\n{GetStackTrace(exception)}";
#endif
}
if (e.IsTerminating) message += "\r\n\r\n<app_name> will be closed.";
// showing message to the user
MessageBox.Show(message, "Unhandled Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
#if DEBUG
private static string GetStackTrace(Exception exception)
{
var trace = new System.Diagnostics.StackTrace(exception, fNeedFileInfo: true);
var frames = trace.GetFrames()
.Select((f, i) => {
var filename = f.GetFileName();
var methodInfo = f.GetMethod();
var frame = $"#{i} in the method {methodInfo.DeclaringType.FullName}.{methodInfo.Name}()";
if (filename != null) frame += $" (source file: {System.IO.Path.GetFileName(filename)}#{f.GetFileLineNumber()}:{f.GetFileColumnNumber()})";
return frame;
});
return $"Full stack trace ({trace.FrameCount} frames total):\r\n{string.Join("\r\n", frames)}";
}
#endif
Now, when unhandled exception occurring - there will be a message box, that shows full exception message (and inner exceptions messages). There was also a full stack trace for Debug build with method name, line number and source filename where exception occure.
About HandleProcessCorruptedStateExceptions
You mention a HandleProcessCorruptedStateExceptions attribute in your comment. The docs clearly says that you shouldn't use it unless you absolutely sure that you need it.
Corrupted process state exceptions are exceptions that indicate that
the state of a process has been corrupted. We do not recommend
executing your application in this state.
By default, the common language runtime (CLR) does not deliver these
exceptions to managed code, and the try/catch blocks (and other
exception-handling clauses) are not invoked for them. If you are
absolutely sure that you want to maintain your handling of these
exceptions, you must apply the
HandleProcessCorruptedStateExceptionsAttribute attribute to the method
whose exception-handling clauses you want to execute. The CLR delivers
the corrupted process state exception to applicable exception clauses
only in methods that have both the
HandleProcessCorruptedStateExceptionsAttribute and
SecurityCriticalAttribute attributes.
Corrupted process state means that some really catastrophic things happens and it safer for your app to die right now. If you are still not scared enough, here is the Main() method from the example above with the HandleProcessCorruptedStateExceptions attribute set:
[STAThread]
[HandleProcessCorruptedStateExceptions, SecurityCritical]
static void Main()
{
try
{
// add UnhandledException handler
// AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
// * in this particular case is not quite useful to handle this exceptions,
// because you already wrap your entire application in a try/catch block
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
catch (Exception ex)
{
// handle it somehow
}
}

Unobserved exception was rethrown despite awaiting the Task and catching Exception

I have code that catches all exceptions that are thrown by a server call as follows:
new public Task SaveAsync()
{
return ServerException.Wrap(base.SaveAsync);
}
Where ServerException.Wrap looks like:
public static async Task<T> Wrap<T>(Func<Task<T>> func)
{
try
{
return await func();
}
catch (Exception ex)
{
// This is an internal error that shouldn't happen.
throw new ServerException(ex);
}
}
public static async Task Wrap(Func<Task> func)
{
await Wrap(async () =>
{
await func();
return true;
});
}
And then I have a function that calls SaveAsync as follows:
try
{
await problem.SaveAsync();
}
catch (ServerException ex)
{
Logger.LogException("Error saving problem.", ex);
}
I have some internal error that generates an exception which I catch in the above line and then it gets logged as follows:
2015-10-20 11:20:44.502 [Line 99] Error saving problem. (Exception:
Exceptions.ServerException: ---> System.ArgumentException: An item
with the same key has already been added. at
System.ThrowHelper.ThrowArgumentException (ExceptionResource resource)
[0x00000] in
/Users/builder/data/lanes/1977/2c66d2fe/source/mono/external/referencesource/mscorlib/system/throwhelper.cs:74
However a few seconds later I get an unhanded exception warning that gets logged:
2015-10-20 11:21:16.352 Warning: Unhandled exception:
System.AggregateException: A Task's exception(s) were not observed
either by Waiting on the Task or accessing its Exception property. As
a result, the unobserved exception was rethrown by the finalizer
thread. ---> System.ArgumentException: An item with the same key has
already been added. at System.ThrowHelper.ThrowArgumentException
(ExceptionResource resource) [0x00000] in
/Users/builder/data/lanes/1977/2c66d2fe/source/mono/external/referencesource/mscorlib/system/throwhelper.cs:74
Why do I get the second unobserved exception, even though I am catching and handling the first exception? This exception seems to be thrown by my ServerException.Wrap method.
I am using MonoTouch.
You need to explicitly set the exception to observed.
For that, you need to subscribe to the TaskScheduler's UnobservedTaskException event, and set it explicitly to observed (call SetObserved() on it).
See here:
UnobservedTaskException being throw...
EDIT:
Of course, you can also just catch AggregateException as well, or use ContinueWith() to observe and resume the task.
See the bottom of the official documentation:
Exception Handling (MSDN)

Finally is not executed when in a Thread running in a Windows Service

Can anyone explain why this finally block is not executed? I have read posts about when to expect finally block not be executed, but this seems to be another case. This code needs TopShelf and log4net. I am running .net 4.5
I guess it must be the Windows Service engine that kicks in on unhandled exceptions, but why is it running before the finally block has finished?
using log4net;
using log4net.Config;
using System;
using System.Threading;
using Topshelf;
namespace ConsoleApplication1
{
public class HostMain
{
static void Main(string[] args)
{
HostFactory.Run(x =>
{
x.Service<HostMain>(s =>
{
s.ConstructUsing(name => new HostMain());
s.WhenStarted(tc => tc.Start());
s.WhenStopped(tc => tc.Stop());
});
x.RunAsLocalSystem();
x.SetServiceName("TimerTest");
});
}
public void Stop()
{
LogManager.GetLogger("MyLog").Info("stopping");
}
public void Start()
{
XmlConfigurator.Configure();
LogManager.GetLogger("MyLog").Info("starting");
new Thread(StartServiceCode).Start();
}
public void StartServiceCode()
{
try
{
LogManager.GetLogger("MyLog").Info("throwing");
throw new ApplicationException();
}
finally
{
LogManager.GetLogger("MyLog").Info("finally");
}
}
}
}
outputs
starting
throwing
stopping
EDIT: Please comment why you are downgrading, maybe you don't understand the problem? I see a big problem here. You write some domain logic that does important stuff in the finally clause on Exception. Then if you host the logic in a Windows Service the design suddenly is broken.
From MDSN try-finally (C# Reference)
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
This is by design, .NET has chosen to terminate your application, reason is, there is something terribly wrong, something didn't work as expected, by calling finally, we don't want to do more damage, so best is to end the application.
What if finally throws one more exception, where does that go? If application is about to close, it may have closed or started closing managed resources and accessing them for logging in finally could turn out to be fatal as well.
Sorry about this being an answer, but couldn't comment.
I couldn't find anything specific about the windows service, but I'm assuming it uses background/foreground threading to execute the code.
And in terms of threading, the finally block is sometimes voided (if the thread is aborted or interrupted unexpectedly) -
http://blog.goyello.com/2014/01/21/threading-in-c-7-things-you-should-always-remember-about/
Or for a more official post - (Look for the foreground/background threading section)
https://msdn.microsoft.com/en-us/library/orm-9780596527570-03-19.aspx
Hopefully it helps you a little
Have you made sure that the logger is getting a chance to flush to disk before the logger is destroyed when the service stops?
Edit
When a service starts it happens on a new thread. Within the Topshelf code there is an AppDomain.CurrentDomain.UnhandledException += CatchUnhandledException; handler.
void CatchUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
_log.Fatal("The service threw an unhandled exception", (Exception)e.ExceptionObject);
HostLogger.Shutdown();
if (e.IsTerminating)
{
_exitCode = TopshelfExitCode.UnhandledServiceException;
_exit.Set();
#if !NET35
// it isn't likely that a TPL thread should land here, but if it does let's no block it
if (Task.CurrentId.HasValue)
{
return;
}
#endif
// this is evil, but perhaps a good thing to let us clean up properly.
int deadThreadId = Interlocked.Increment(ref _deadThread);
Thread.CurrentThread.IsBackground = true;
Thread.CurrentThread.Name = "Unhandled Exception " + deadThreadId.ToString();
while (true)
Thread.Sleep(TimeSpan.FromHours(1));
}
}
This catches the unhandled exception, and stops the service by setting the manualresetevent (this is the only thing that is blocking the service from ending).
After sleep is called, the thread is signalled and your finally block, which is on the service thread is killed.
The code then exits.
This is wired up in the Run() method in ConsoleRunHost.
public TopshelfExitCode Run()
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
AppDomain.CurrentDomain.UnhandledException += CatchUnhandledException;
if (_environment.IsServiceInstalled(_settings.ServiceName))
{
if (!_environment.IsServiceStopped(_settings.ServiceName))
{
_log.ErrorFormat("The {0} service is running and must be stopped before running via the console",
_settings.ServiceName);
return TopshelfExitCode.ServiceAlreadyRunning;
}
}
bool started = false;
try
{
_log.Debug("Starting up as a console application");
_log.Debug("Thread.CurrentThread.Name");
_log.Debug(Thread.CurrentThread.Name);
_exit = new ManualResetEvent(false);
_exitCode = TopshelfExitCode.Ok;
Console.Title = _settings.DisplayName;
Console.CancelKeyPress += HandleCancelKeyPress;
if (!_serviceHandle.Start(this))
throw new TopshelfException("The service failed to start (return false).");
started = true;
_log.InfoFormat("The {0} service is now running, press Control+C to exit.", _settings.ServiceName);
_exit.WaitOne();
}
catch (Exception ex)
{
_log.Error("An exception occurred", ex);
return TopshelfExitCode.AbnormalExit;
}
finally
{
if (started)
StopService();
_exit.Close();
(_exit as IDisposable).Dispose();
HostLogger.Shutdown();
}
return _exitCode;
}
There is no guarantee that finally will be called for certain exceptions.
Since this program runs as a Windows service it is managed by Windows. Windows detects that something went wrong because of the ApplicationException call and it sends Stop to the service which abort the thread before the finally block is executed.
The "finally" block is never executed because Windows pulls the rug from under. This is pefectly logical when you remind how exception handling works :
try {
// Do stuff
} catch (Exception e) {
// Executed first
} finally {
// Executed last
}
Since you didn't provide a catch block the ApplicationException is propagated up to the other layers and ultimately to Windows service management which handle it by sending the stop request thus aborting the thread.
Side notes :
Unmanaged exception in a service is very bad : obviously you should add a catch block and log exceptions.
Normally the Stop function is used to tell the working thread it needs to stop. This will give the thread a chance to stop in clean way. Here is a good example.
Edit :
Here is a sample of what I would do. It is more like pseudo-code but you should get the idea.
public void StartServiceCode(object state)
{
bool stopTimer = false;
try
{
LogManager.GetLogger("MyLog").Info("Locking");
lock (thisLock) {
LogManager.GetLogger("MyLog").Info("Throwing");
throw new ApplicationException();
}
} catch (Exception e) {
// The lock is relased automatically
// Logging the error (best practice)
LogManager.GetLogger("MyLog").Info("Exception occurred...");
// If severe, we need to stop the timer
if (e is StackOverflowException || e is OutOfMemoryException) stopTimer = true;
} finally {
// Always clean up
LogManager.GetLogger("MyLog").Info("finally");
}
// Do we need to stop?
if (stopTimer) {
LogManager.GetLogger("MyLog").Info("Severe exception : stopping");
// You need to keep a reference to the timer. (yes, a timer can stop itself)
timer.Stop();
}
}
The linked article explains why the finally block of a method run into a windows service provided by TopShelf library that raises an unhandled exception, it isn't executed: https://lowleveldesign.wordpress.com/2012/12/03/try-finally-topshelf-winsvc/
The problem seems related to a portion of code in the topshelf library that sleeps the thread that has raised the exception.
Follows an excerpt of the code responsible for the sleep call on the thread, this method belongs to TopShelf library
...
void CatchUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
_log.Error("The service threw an unhandled exception", (Exception)e.ExceptionObject);
...
int deadThreadId = Interlocked.Increment(ref _deadThread);
Thread.CurrentThread.IsBackground = true;
Thread.CurrentThread.Name = "Unhandled Exception " + deadThreadId.ToString();
while (true)
Thread.Sleep(TimeSpan.FromHours(1));
}
...

Exception Thrown from Thread Pool Thread shown as Unhandled

I am firing off a Task of on a background thread pool thread via the following method
private async Task LoadCoreMatchDataAsync()
{
string errorMessage = String.Empty;
...
try
{
if (!HasConnection)
return;
IProgress<string> progressIndicator = new Progress<string>(LoadProgress);
EventsCollection = new BindableCollection<Taurus.MatchDetails>(
await MatchDataService.GetCollectionAsync(
this.client, progressIndicator, this.token));
...
}
catch (TimeoutException toe)
{
errorMessage = String.Format(
"Retrieval of the MatchDetails using connection " +
"\"{0}\" failed with the following TimeoutException: \"{1}\".",
this.ConnectionString,
toe.Message);
}
catch (OperationCanceledException)
{
// Do nothing, cancel silently.
}
// Display any errors.
if (!String.IsNullOrEmpty(errorMessage))
{
await dialogManager.ShowDialog<MessageDialogResult>(
new MessageBoxViewModel("Connection Timeout", errorMessage, mbs));
HasConnection = false;
}
}
where the GetCollectionAsync(...) method is
public async Task<BindableCollection<Taurus.MatchDetails>> GetCollectionAsync(
MongoClient client, IProgress<string> progressIndicator, CancellationToken token)
{
return await Task.Factory.StartNew<BindableCollection<Taurus.MatchDetails>>(() =>
{
... // Somewhere in here we get a TimeoutException thrown.
}, token);
}
the problem is that when in my call to await MatchDataService.GetCollectionAsync(...) I get an expected TimeoutException, VS2012 throws "a TimeoutException was unhandled by user code" message, when clearly I am handling the exception in the "continuation" in the correct way. If I continue rather than break, the exception is indeed caught and I get my expected error message. I am just not sure why VS2012 is telling me that the exception is unahandled?
I am essentially doing what is described clearly in on of Jon Skeets answers here https://stackoverflow.com/a/19865613/626442.
Thanks for your time.
You have "Just My Code" turned on (which I mentioned in my answer in the other question you reference). The debugger is indicating that "User code" (Your code) did not handle the exception--which is true. The exception is caught by the framework code and placed into a Task.
Turn off the "Just My Code" debugger setting (in my opinion, it is a feature that only causes confusion and has very limited usefulness).

Async/await exception and Visual Studio 2013 debug output behavior

I'm developing an application in C# that communicates with Dynamics NAV through web services. To reduce duplicate code and because there will be many endpoints, I have created a generic async/await method that executes the service calls and handle exceptions.
The method works but I'm seeing an unexpected behavior in the Visual Studio 2013 output window when an exception occur(and is handled).
Test code and output can be seen below.
My concern is the "A first chance exception of type..." lines which I'm seeing 4 times when using the async/await methods. Does this exception really occur 4 times?
When calling the service synchronously there's only one exception line which is expected.
Is this just Visual Studio 2013 or is there something wrong with my async/await code?
Is there maybe a better way of doing what I'm trying to accomplish?
class Program
{
static void Main(string[] args)
{
Debug.WriteLine("Synchronous...");
try
{
TestFunctions_PortClient service = new TestFunctions_PortClient();
service.Open();
string result = service.ErrorTest();
Debug.WriteLine(result);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
Debug.WriteLine(string.Empty);
Debug.WriteLine("Async...");
NavServiceTest navService = new NavServiceTest();
navService.TestAsync();
Console.ReadLine();
}
}
class NavServiceTest
{
public async void TestAsync()
{
try
{
string result = await CallServiceAsync();
Debug.WriteLine(result);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
private async Task<string> CallServiceAsync()
{
TestFunctions_PortClient service = new TestFunctions_PortClient();
service.Open();
ErrorTest_Result result = await ExecuteServiceAsync<ErrorTest_Result>(
service.InnerChannel,
service.Endpoint,
service.ErrorTestAsync());
return result.return_value;
}
private async Task<T> ExecuteServiceAsync<T>(IClientChannel channel, ServiceEndpoint endpoint, Task<T> source)
{
var tcs = new TaskCompletionSource<T>();
Task<T> task = tcs.Task;
try
{
Debug.WriteLine("ExecuteServiceAsync");
tcs.TrySetResult(await source);
}
catch (EndpointNotFoundException ex)
{
Debug.WriteLine("EndpointNotFoundException");
tcs.TrySetException(ex);
}
catch (FaultException ex)
{
Debug.WriteLine("FaultException");
tcs.TrySetException(ex);
}
catch (Exception ex)
{
Debug.WriteLine("Exception");
tcs.TrySetException(ex);
}
finally
{
if (channel != null)
{
if (channel.State == CommunicationState.Faulted)
channel.Abort();
else
channel.Close();
}
}
if (task.IsFaulted)
{
throw task.Exception.InnerException;
}
return task.Result;
}
}
Here's the output of the code above.
Synchronous...
A first chance exception of type 'System.ServiceModel.FaultException' occurred in mscorlib.dll
Error from NAV
Async...
ExecuteServiceAsync
A first chance exception of type 'System.ServiceModel.FaultException' occurred in mscorlib.dll
FaultException
A first chance exception of type 'System.ServiceModel.FaultException' occurred in ServiceTest.exe
A first chance exception of type 'System.ServiceModel.FaultException' occurred in mscorlib.dll
A first chance exception of type 'System.ServiceModel.FaultException' occurred in mscorlib.dll
Error from NAV
When an exception occurs in an async method, it doesn't just propagate up the stack like it does in synchronous code. Heck, the logical stack is likely not to be there any more.
Instead, the exception is stored in the task which represents the asynchronous operation. Then, when you await the asynchronous operation, the GetResult method of the TaskAwaiter will rethrow the original exception. If that isn't caught in your code, then it will be caught by the compiler-generated code again and put into the task that represents that operation, etc. So if you have a chain of asynchronous methods (as is often the case) and the deepest one throws an exception, the exception propagation will actually be a "throw in GetResult, catch, stuff into task" per link in the chain.
So yes, the exception is being thrown four times, in order to effectively only be thrown once. If you're worried about the efficiency of that, I suspect it's not too bad - because the logical stack trace is only determined once. I dare say it's less efficient than the synchronous version, but my general philosophy is that if you're seeing so many exceptions that they're affecting your performance significantly, then either you're overusing exceptions or your system is in a really bad state anyway, and performance is the least of your worries.

Categories

Resources