How to avoid multiple messageboxes continuous display? - c#

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;
}

Related

How to catch all exceptions in try catch block in Xamarin.Android

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;
}

How to get updates and reply telegram bot?

This is my code that i try to connect to a telegram bot
namespace telegramUpdate
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
TelegramBotClient bot = new TelegramBotClient("xxxxxxxxx");
int offset = 23;
Update temp = null;
private void Form1_Load(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
try
{
var m = Task.Run(async()=> bot.GetUpdatesAsync(offset,50)).Result;
foreach (var x in m.Result)
{
switch (x.Type)
{
case UpdateType.MessageUpdate:
temp = x;
backgroundWorker1.ReportProgress(0);
bot.SendTextMessageAsync(x.Message.Chat.Id, ":)").ConfigureAwait(false);
break;
}
offset = x.Id+1;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = temp.Message.From.FirstName;
}
}
}
after ruining message box show "One or more errors occurred." what is the problem? telegram bot should reply ":)" but it don't. I can not find out if m receive any updates or not.
try this:
bot.SendTextMessageAsync(x.Message.Chat.Id, ":)").GetAwaiter().GetResult();
you didn't execute the task. just it
to me this same error happen recently (the code was working on Feb 2020 but did not work later) when making bot.SendTextMessageAsync i received same exception. After some research i found this topic [Telegram Bot stops with An unhandled exception of type 'System.AggregateException' occurred in mscorlib.dll
that actually solved my problem.
using System.Net;
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Why does subscription to Application.ThreadException swallow the exception?

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);
}
}

Exception when closing Form (thread + invoke)

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();
}

Serial communication in c#

I have made a simple windows form with a ComboBox, TextBox and two Buttons to setup a serial protocol with my hardware.
However, whenever I send something I do get reply from hardware but C# doesn't display it. Instead it gives an exception saying that the operation has timed out. I even used an oscilloscope to check if I received something and it was positive. But C# doesn't display the code as stated before.
I am attaching my code below. Anyhelp would be welcome. Thanks in advance.
public partial class Form3 : Form
{
string buffer;
public SerialPort myComPort = new SerialPort();
delegate void setTextCallback(string text);
public Form3()
{
InitializeComponent();
}
private void Form3_Load(object sender, EventArgs e)
{
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_PnPEntity");
foreach (ManagementObject queryObj in searcher.Get())
{
if (queryObj["Caption"].ToString().Contains("(COM"))
{
comboBox1.Items.Add(queryObj["Caption"]);
}
}
comboBox1.Text = comboBox1.Items[0].ToString();
}
catch (ManagementException ex)
{
MessageBox.Show(ex.Message);
}
}
private void setText(string text)
{
if (textBox1.InvokeRequired)
{
setTextCallback tcb = new setTextCallback(setText);
this.Invoke(tcb, new object[] { text });
}
else
{
textBox1.Text = text;
}
}
void myComPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
string myString = myComPort.ReadLine();
setText(myString);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
private void button1_Click(object sender, EventArgs e)
{
myComPort.Close();
// button1.Enabled = false;
string name = comboBox1.Text;
string[] words = name.Split('(', ')');
myComPort.PortName = words[1];
myComPort.ReadTimeout = 5000;
// myComPort.WriteTimeout = 500;
myComPort.BaudRate = 9600;
myComPort.DataBits = 8;
myComPort.StopBits = StopBits.One;
myComPort.Parity = Parity.None;
myComPort.DataReceived += new SerialDataReceivedEventHandler(myComPort_DataReceived);
myComPort.Open();
}
private void button2_Click(object sender, EventArgs e)
{
myComPort.WriteLine("?GV1\r");
}
}
It say
...The DataReceived event is not guaranteed to be raised for every byte received...
Try something like:
private static void DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// prevent error with closed port to appears
if (!_port.IsOpen)
return;
// read data
if (_port.BytesToRead >= 1)
{
// ...
// read data into a buffer _port.ReadByte()
DataReceived(sender, e);
}
// ...
// if buffer contains data, process them
}
Have a look at this url:
http://csharp.simpleserial.com/
And this url for WMI:
http://www.codeproject.com/Articles/32330/A-Useful-WMI-Tool-How-To-Find-USB-to-Serial-Adapto

Categories

Resources