Suppose I have an exception throw in the message loop:
private void timer1_Tick(object sender, EventArgs e)
{
throw new Exception("yehaaaa!!!!");
}
By default, this throws & displays the generic error dialog to user. (that's what I want)
However if I add the following subscription to Application.ThreadException:
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
//_raygunClient.Send(e.Exception);
}
Then the exception is swallowed.
Why?
& how can I have it throw to the user normally?
It's all right there in the reference source:
internal void OnThreadException(Exception t) {
if (GetState(STATE_INTHREADEXCEPTION)) return;
SetState(STATE_INTHREADEXCEPTION, true);
try {
if (threadExceptionHandler != null) {
threadExceptionHandler(Thread.CurrentThread, new ThreadExceptionEventArgs(t));
}
else {
if (SystemInformation.UserInteractive) {
ThreadExceptionDialog td = new ThreadExceptionDialog(t);
If there is a handler it is invoked otherwise some standard code is run. If you want to show the standard dialog, use ThreadExceptionDialog and handle the DialogResult the same way. In my own code there is something to this effect, which seems to work:
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
Exception exception = e.Exception;
_Logger.Error(e.Exception, "An unhandled forms application exception occurred");
// Show the same default dialog
if (SystemInformation.UserInteractive)
{
using (ThreadExceptionDialog dialog = new ThreadExceptionDialog(exception))
{
if (dialog.ShowDialog() == DialogResult.Cancel)
return;
}
Application.Exit();
Environment.Exit(0);
}
}
Related
How to catch all exceptions in try catch block in Xamarin.Android
I am very frustrated on how Xamarin.Android handles unhandled exception which is very weird, I added three exceptions for all api queries respectively:
try
{
// api query using `refit`
// json parsing using `newtonsoft`
}
catch(System.OperationCanceledException e)
{
// user cancelled the query, show option to retry
}
catch(ApiException apiException)
{
// theres an api exception , show error message to users , show option to retry
}
catch(Exception e)
{
// unknown exception ignore , show error message to users , show option to retry
}
This try catch blocks works most of the time, but there is one certain scenario when our server is down, and it just throws exception and crashes the app over and over again until the server is back up.
This is the exception that keeps on bugging us :
Xamarin caused by: android.runtime.JavaProxyThrowable: Newtonsoft.Json.JsonReaderException
As you can see in JsonReaderException hierarchy, it inherited System.Exception which is the last catch block i used.
and I checked this JsonReaderException it extends from Exception , In which our try catch block should handle it.
Now im wondering is there any way that we can catch all those pesky unhandled exceptions?
I'm getting unhandled exceptions in this way
public void Init()
{
AndroidEnvironment.UnhandledExceptionRaiser += OnAndroidEnvironmentUnhandledExceptionRaiser;
AppDomain.CurrentDomain.UnhandledException += OnCurrentDomainUnhandledException;
TaskScheduler.UnobservedTaskException += OnTaskSchedulerUnobservedTaskException;
var currentHandler = Java.Lang.Thread.DefaultUncaughtExceptionHandler;
var exceptionHandler = currentHandler as UncaughtExceptionHandler;
if (exceptionHandler != null)
{
exceptionHandler.SetHandler(HandleUncaughtException);
}
else
{
Java.Lang.Thread.DefaultUncaughtExceptionHandler = new UncaughtExceptionHandler(currentHandler, HandleUncaughtException);
}
}
private void OnAndroidEnvironmentUnhandledExceptionRaiser(object sender, RaiseThrowableEventArgs e)
{
AndroidEnvironment.UnhandledExceptionRaiser -= OnAndroidEnvironmentUnhandledExceptionRaiser;
_logger.LogFatal($"AndroidEnvironment.UnhandledExceptionRaiser.", e.Exception);
e.Handled = true;
}
private void OnCurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException -= OnCurrentDomainUnhandledException;
var ex = e.ExceptionObject as Exception;
if (ex != null)
{
_logger.LogFatal("AppDomain.CurrentDomain.UnhandledException.", ex);
}
else
{
_logger.LogFatal($"AppDomain.CurrentDomain.UnhandledException. ---> {e.ExceptionObject}");
}
}
private void OnTaskSchedulerUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
_logger.LogFatal("TaskScheduler.UnobservedTaskException.", e.Exception);
}
private bool HandleUncaughtException(Java.Lang.Throwable ex)
{
_logger.LogFatal("Thread.DefaultUncaughtExceptionHandler.", ex);
return true;
}
I'm using the UndhandledException provided by the AppDomain, what I did is essentially this:
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
}
static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e)
{
e.ExceptionObject.Message? <- there is no message
Console.WriteLine(e.ExceptionObject.ToString());
Console.WriteLine("Press a key for exit.");
Console.ReadLine();
Environment.Exit(1);
}
how you can see I can't access to the message property, but if I set a break point I can see on the e variable the Message property, why I can't use this?
The problem is that ExceptionObject is an object. You can cast it to Exception in order to get the Message
var exception = (e.ExceptionObject as Exception);
if (exception != null)
{
message = exception.Message;
}
or MSDN suggests to cast it this way
Exception exception = (Exception) e.ExceptionObject;
var message = exception.Message;
I have a problem with WPF MessageBox,its due to when internet connection is not available. I need the message to displays once only, but it shows multiple times.
private void Application_Startup(object sender, StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(cc);
}
void cc(object sender, UnhandledExceptionEventArgs e)
{
Exception ex = e.ExceptionObject as Exception;
MessageBox.Show(ex.Message, "Uncaught", MessageBoxButton.OK);
}
Simple.
You should confirm before you show message box.
// message box flag.
bool canIShowMessageBox = true;
// for thread lock.
object exLocker = new object();
void cc(object sender, UnhandledExceptionEventArgs e)
{
lock(exLocker)
{
if (canIShowMessageBox)
canIShowMessageBox = false;
else
return;
}
Exception ex = e.ExceptionObject as Exception;
MessageBox.Show(ex.Message, "Uncaught", MessageBoxButton.OK);
lock(exLocker)
canIShowMessageBox = true;
}
I have just started to learn about threads and methodinvoking in c#, but I have come across a problem which I couldn't find the solution of.
I made a basic C# form program which keeps updating and displaying a number, by starting a thread and invoke delegate.
Starting new thread on Form1_load:
private void Form1_Load(object sender, EventArgs e)
{
t = new System.Threading.Thread(DoThisAllTheTime);
t.Start();
}
Public void DoThisAllTheTime (which keeps updating the number) :
public void DoThisAllTheTime()
{
while(true)
{
if (!this.IsDisposed)
{
number += 1;
MethodInvoker yolo = delegate() { label1.Text = number.ToString(); };
this.Invoke(yolo);
}
}
}
Now when I click the X button of the form, I get the following exception:
'An unhandled exception of type 'System.ObjectDisposedException' occurred in System.Windows.Forms.dll
Can't update a deleted object'
While I actually did check if the form was disposed or not.
EDIT: I added catch (ObjectDisposedException ex) to the code which fixed the problem.
Working code:
public void DoThisAllTheTime()
{
while(true)
{
number += 1;
try {
MethodInvoker yolo = delegate() { label1.Text = number.ToString(); };
this.Invoke(yolo);
}
catch (ObjectDisposedException ex)
{
t.Abort();
}
}
}
Your call to this.IsDisposed is always out of date. You need to intercept your form closing event and stop the thread explicitly. Then you won't have to do that IsDisposed test at all.
There are many ways you can do this. Personally, I would use the System.Threading.Tasks namespace, but if you want to keep your use of System.Threading, you should define a member variable _updateThread, and launch it in your load event:
_updateThread = new System.Threading.Thread(DoThisAllTheTime);
_updateThread.Start();
Then in your closing event:
private void Form1_Closing(object sender, CancelEventArgs e)
{
_stopCounting = true;
_updateThread.Join();
}
Finally, replace the IsDisposed test with a check on the value of your new _stopCounting member variable:
public void DoThisAllTheTime()
{
MethodInvoker yolo = delegate() { label1.Text = number.ToString(); };
while(!_stopCounting)
{
number += 1;
this.Invoke(yolo);
}
}
Just put this override in your form class:
protected override void OnClosing(CancelEventArgs e) {
t.Abort();
base.OnClosing(e);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Thread.CurrentThread.Abort();
}
I have a GUI form with a checkbox button for Start/Stop. When the program starts, clicking Start and Stop works once. When I try and click Start again after I stop the recording, I get a NullReferenceException.
An unhandled exception of type 'System.NullReferenceException' occurred in NAudio.dll
Additional information: Object reference not set to an instance of an object.
at this line in my Program.cs file:
Application.Run(new GUI());
Here is my Start/Stop button in my GUI form:
public GUI()
{
InitializeComponent();
InitializeAudio();
}
private void btnStartStop_CheckedChanged(object sender, EventArgs e)
{
if (btnStartStop.Checked)
{
waveInDevice.StartRecording();
waveOutDevice.Play();
btnStartStop.Text = "Stop";
}
else
{
btnStartStop.Text = "Start";
waveInDevice.StopRecording();
waveOutDevice.Stop();
}
}
private void InitializeAudio()
{
buffer = new BufferedWaveProvider(waveInDevice.WaveFormat);
buffer.DiscardOnBufferOverflow = true;
waveInDevice.DataAvailable += new EventHandler<WaveInEventArgs>(waveInDevice_DataAvailable);
waveOutDevice.Init(buffer);
}