Throwing exceptions in callback method for Timers - c#

I was unable to find an answer to this question anywhere...
What happens with the exceptions thrown in the callback method for System.Threading.Timer, (or in the event handler for System.Timers.Timer). Is the exception propagated to the thread on which the timer was created or is the exception lost?
What are the side-effects of throwing an exception within the timer's callback functions?
What would be the right way to signalize to the timer's creation thread that the exception in the worker thread (callback method) has been thrown?
Thanks for your time.

The exception is not passed back to the calling thread. If you want it to be, you can add a catch block and figure out a way to signal the calling thread. If the calling thread is a WinForms or WPF UI thread, you can use the SynchronizationContext class to pass a call to the UI thread. Otherwise, you could use a thread-safe queue (or a sync lock) and check it periodically in the other thread.
System.Timers.Timer will silently swallow exceptions and continue the timer (although this is subject to change in future versions of the framework); System.Threading.Timer will terminate the program.

I don't know what the best option is, but when I'm using a callback timer I'm normally throwing exceptions and letting them bubble up to the main callback routine, where I handle them gracefully. The thread continues to run on the timer as it should.
Unhandled exceptions in the thread (System.Threading.Timer) will stop your entire program.

I dont know if it is a best solution, but what I did was a small workaround. My calling thread has subscribed to an event for catching exceptions from across the threads. So when exception occurs in some thread, say in TimerElapsed event, then form the catch block I raise the event passing exception object as an argument to the event.
EventHolderCallingClass: It must define delegate and event as shown below.
public class EventHolderCallingClass
{
public delegate void HandleExceptionEventDelegate(Exception exception);
public event HandleExceptionEventDelegate HandleExceptionEvent ;
void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
try
{
//some operation which caused exception.
}
catch(Exception exception)
{
if(HandleExceptionEvent!=null)
HandleExceptionEvent(exception)
}
}
}
Event Handler Class (Exception Handler):
public EventHandlerClassConstructor()
{
EventHolderCallingClass.HandleExceptionEvent += new EventHolderCallingClass.HandleExceptionEventDelegate(HandleExceptionEventHandler);
}
void HandleExceptionEventHandler(Exception exception)
{
//handle exception here.
}

From my humble test under windows 10 framework 4.6, the thread used by the SystemTimers.Timer elapsed event will not propagate the unhandled exception.
I needed to fire a event to the main thread to notify the unhandled exception happened.

Related

how to crash the main process if there is unhandled exception inside background thread

I have a publisher, dispatcher, subscriber.
publisher publish event through dispatcher to subscriber.
subscriber is a com object embedded in S.exe can be callback from dispatcher.exe when specific event coming from publisher.exe.
I expect any exception inside the subscriber to terminate the S.exe.
I did my investigation:
task, with
configuration can terminate the main process. related article,
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskscheduler.unobservedtaskexception?view=netframework-4.7.2
new a thread in my code, without any specific configuration can
also, any unhandled exception inside the thread can crash the main
process. related article,
https://learn.microsoft.com/en-us/dotnet/standard/threading/exceptions-in-managed-threads
two attributes of one thread: {isbackground, isThreadPoolThread}.
task is {true, true}
artificial thread is {true, false},
subscriber callback thread is {true, false}.
is there any other configuration, like , can set to control whether or not to crash the main process?
You can handle AppDomain.CurrentDomain.UnhandledException event in which you can get the current process by using Process.GetCurrentProcess() and kill that process so your exe will terminate.
Put this line Main() in Program.cs:
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException
Then implement CurrentDomain_UnhandledException as below.
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var currentProcess = Process.GetCurrentProcess();
currentProcess.Kill();
}
This is just concept as per your problem statement. You can change it as per your need.
Any exception inside a COM was wrapped as a HRESULT return to it's client by RCW.
So, no way to crash the main process when the exception was thrown inside a COM thread.
The answer may be related with:
COM methods report errors by returning HRESULTs; .NET methods report them by throwing exceptions. The runtime handles the transition between the two. Each exception class in the .NET Framework maps to an HRESULT.
from https://learn.microsoft.com/en-us/dotnet/framework/interop/how-to-map-hresults-and-exceptions
and other helpful links:
https://learn.microsoft.com/en-us/dotnet/framework/interop/runtime-callable-wrapper
https://learn.microsoft.com/en-us/dotnet/framework/interop/com-callable-wrapper

How do I handle an exception thrown by a COM library from a worker thread?

I am building a .Net application which is using a COM library (I am really bad at COM, but its a library which I need to register using regsvr32 and once referenced in visual studio it says the file type is ActiveX).
In a console application, I am creating a new COM object like this :
static void Main(string[] args)
{
var comObj = new EikonDesktopDataAPI();
comObj.OnStatusChanged += EikonDesktopDataApi_OnStatusChanged;
comObj.Initialize();
Console.ReadLine();
}
private void EikonDesktopDataApi_OnStatusChanged(EEikonStatus status)
{
try{
throw new Exception("An exception 1.");
}catch(Exception ex){
throw new Exception("Tell the main thread." , ex);
}
}
So the application initialise the Api synchronously on the Main thread and wait on Console.ReadLine(). After a few seconds the EikonDesktopDataApi_OnStatusChanged event is triggered. When debugging, I can see that this is handled on a worker thread. As the exception is thrown on another thread, the console application doesn't crash. How can I catch this exception?
I tried to add the SLAThreadAttribute on the Main method, but this cause the event to never be raised.
I also tried to use :
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
But the exception is not handled neither.
The only way I found to "catch" the exception was to use :
AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
But this cause the handler method to handle 3 exceptions: "An exception 1", then "Tell the main thread." and finally a "Exception has been thrown by the target of an invocation". Which means I will handle even "caught" exception which is impractical.
Any ideas?
EDIT:
I did a WPF application, where I am instantiating the COM object from the main thread. Once initialized the event is raised and my event handler runs on the MAIN thread, but if I throw an exception, it wont crash the application or raise an Unhandledexception event. I really don't understand why exceptions thrown on the main thread just does nothing.

catch block not catching exception in another thread

method A()
{
try
{
Thread t = new Thread(new ThreadStart(B));
t.Start();
}
catch(exception e)
{
//show message of exception
}
}
method B()
{
// getDBQuery
}
a exception in B but not catched.
does it legal in .net?
Correct, exceptions from a Thread are not forwarded to the caller, the Thread should handle this by itself.
The most general answer is that you should not be using a (bare) Thread here. It's not efficient and not convenient.
When you use a Task, the exception is stored and raised when you cal Wait() or Result.
When A is finished executing B might still be running as it is on an independent thread. For that reason it is impossible by principle for A to catch all exceptions that B produces.
Move the try-catch to inside of B. The Thread class does not forward exceptions.
Better yet, use Task which allows you to propagate and inspect exceptions.

App enters unknown/locked state after handling UnhandledException

In my App.xaml.cs I have events to handle DispatcherUnhandledExceptions (UI thread) and UnhandledException (Non UI thread). When I throw an exception inside dispatcher.Invoke, the dispatcherhandler catches the exception and handles it. I am setting e.Handled to true after logging the exception. Now the strange behaviour, if i throw the exception outside of the dispatcher.Invoke as a regualr statment, control is sent to the dispatcher exception handler,but after the method is processed the app basically loses control but I can tell its still running by looking at the stop button in vs.
one more thing, if i set e.handled to false, control is sent to the non-ui thread exception handler.
So what puzzles me is why is the application locking after handling the exceptiono in the dispatcher handler?
here's my code
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
// log exception here
e.Handled = true;
} // control is lost after executing this block
private void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
try
{
Exception ex = e.ExceptionObject as Exception;
// log exception here
}
finally
{
Environment.Exit(-1);
}
}
An UnhandledException means that your application is effectively dead. If you get that event then it is too late to do anything to recover from the scenario. Typically you would use this event only to log errors for debugging purposes and maybe attempt to cleanup some unmanaged resources.
The following article gives a detailed explanation of exception handling in WPF.
It seems like the app is able to resume operation if the exception is raised after the OnStartup Event, if the exception is raised in between, the exception is caught and handled but the main window is never shown yet the debugger shows the app as running.
the closest solution I found is to remove complex logic from the constructor of main window to allow onstartup event to execute and do a lot of loading in my MainWindow load event.

Catching unhandled exception on separate threads

I am using the following event to catch unhandled exceptions in the main UI thread.
Application.ThreadException
Unfortunately, it does not catch those unhandled errors in seperate threads. I am aware of
AppDomain.CurrentDomain.UnhandledException
However, this seems to shut down the application upon triggering, where as the former does not.
Is there a way to deal with unhandled exceptions on separate threads, without the application closing?
#Ani have already answered your question. Although I don't agree that unhandled exceptions in threads should terminate applications. Using threads usually means that you have some kind of server application. Bringing it down could result in a lot of angry users.
I've written a small piece about proper exception handling: https://coderr.io/exception-handling
You should always catch exceptions for threads. I usually use the following pattern:
void ThreadMethod(object state)
{
try
{
ActualWorkerMethod();
}
catch (Exception err)
{
_logger.Error("Unhandled exception in thread.", err);
}
}
void ActualWorkerMethod()
{
// do something clever
}
It's a whole lot easier to find thread methods that doesn't handle exceptions properly by moving the logic into a seperate method and just keep the try/catch block in the thread method.
Of course you should always handle all exceptions. But if you are currently incapable of doing so, you can try the following:
The application will crash/close after the UnhandledException event handler.
You can just add a delay in the event handler to prevents this. Other threads with no exception (e.g. the main thread) can continue. So the application will not close and can continue. However, the thread with the exception will remain in sleep. And therefor you may get a "memory/thread leak".
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// Log the exception, display it, etc
Debug.WriteLine((e.ExceptionObject as Exception).Message);
Thread.Sleep(100000000);
}
At this moment there is not a better solution.
You may find to change the config file, but i think that is just as dirty: https://stackoverflow.com/a/15348736
Yes, you have to manually catch exceptions on threads.
However, this code:
void ThreadMethod(object state)
{
try
{
ActualWorkerMethod();
}
catch (Exception err)
{
_logger.Error("Unhandled exception in thread.", err);
}
}
void ActualWorkerMethod()
{
// do something clever
}
can be simplified to this using PostSharp:
[LogExceptions]
void ActualWorkerMethod()
{
// do something clever
}

Categories