function calling sequence disturbed due to exception - c#

It may sound very basic but I am stuck in a situation where the function calling sequence is being disturbed due to exception even after exception handling.
I have the following situation in my windows form project (C#) (dummy code only):
private void timer1_Tick(object sender, EventArgs e)
{
try
{
BAL objBAL = new BAL();
objBAL.BL_Function1();
objBAL.BL_Function2();
objBAL.BL_Function3();
objBAL.BL_Function4();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
the above functions are called from the business logic(BL) class which further has function callings of various functions of Data Access Layer (DAL) class.
Now the problem is whenever exception comes in any of the above functions, let's say BL_Function3(), it resets the calling to BL_Function1() which leaves BL_Function4() uncalled, which is not desirable.
My question is:
Is there any way to persists the calling sequence, i.e., if exception occurs at BL_Function2(), it should go ahead and call BL_Function3() and BL_Function4(), and then return back to BL_Function1() in the next timer_tick ?
Any help on this would be appreciated.

You can wrap each method into try..catch:
private void timer1_Tick(object sender, EventArgs e) {
//TODO: you may want to stop timer here...
BAL objBAL = new BAL();
try {
objBAL.BL_Function1();
}
catch (Exception ex) { //TODO: catch more specific exception (not Exception)
// If BL_Function1() fails, show message...
MessageBox.Show(ex.Message);
}
// ...and go ahead
try {
objBAL.BL_Function2();
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
try {
objBAL.BL_Function3();
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
try {
objBAL.BL_Function4();
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
//...and restart the timer here
}
Edit: please note, that the timer keep on ticking when MessageBox is on the screen. You may want to stop the timer for a while and then restart it:
private void timer1_Tick(object sender, EventArgs e) {
// Stop the timer until execution is complete
timer1.Enabled = false;
try {
//Put all the executions here
...
}
finally {
// execution is complete (with or without exceptions), let's restart the timer
timer1.Enabled = true;
}
}

You could use an array to make it cleaner
private void timer1_Tick(object sender, EventArgs e)
{
var objBAL = new BAL();
Action[] functions = { objBAL.BL_Function1, objBAL.BL_Function2, objBAL.BL_Function3, objBAL.BL_Function3 };
foreach (var fun in functions)
{
var funCopy = fun;
try
{
funCopy ();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}

Related

C# How to catch exception in a Task without block UI using wait

I have this code in a button click
private async void btnStart_Click(object sender, EventArgs e)
{
Msg.Clear();
stopWatch.Reset();
timer.Start();
stopWatch.Start();
lblTime.Text = stopWatch.Elapsed.TotalSeconds.ToString("#");
progressBar.MarqueeAnimationSpeed = 30;
try
{
await Task.Factory.StartNew(() =>
{
try
{
Reprocess();
}
catch (Exception ex)
{
Msg.Add(new clsMSG(ex.Message, "Error", DateTime.Now));
timer.Stop();
stopWatch.Stop();
throw;
}
});
}
catch
{
throw;
}
}
and this on the Reprocess method
private void Reprocess()
{
try
{
clsReprocess reprocess = new clsReprocess(tbBD.Text, dtpStart.Value, 50000);
reprocess.Start(reprocess.BD);
}
catch
{
throw;
}
}
when the Reprocess method fails, the Task goes to catch, but the throw fails (the throw inside catch (Exception ex)) and the UI blocks until the reprocess.Start method is completed.
I have two questions:
First: How can I catch the throw in the catch of my button?
Second: How can I prevent the UI blocks?
I hope you can understand me, sorry for my bad english.
You should not use Task.Factory.StartNew; Task.Run is both safer and shorter to write.
Also, you can only access UI controls from the UI thread. This may be the cause of the problems you're seeing, if Msg is data-bound to the UI. Even if it's not, you don't want to access unprotected collections (e.g., List<clsMSG>) from multiple threads.
Applying both of these guidelines reduces the code to:
private async void btnStart_Click(object sender, EventArgs e)
{
Msg.Clear();
stopWatch.Reset();
timer.Start();
stopWatch.Start();
lblTime.Text = stopWatch.Elapsed.TotalSeconds.ToString("#");
progressBar.MarqueeAnimationSpeed = 30;
try
{
await Task.Run(() => Reprocess());
}
catch (Exception ex)
{
Msg.Add(new clsMSG(ex.Message, "Error", DateTime.Now));
timer.Stop();
stopWatch.Stop();
throw;
}
}
If Reprocess throws an exception, that exception will be placed on the task returned from Task.Run. When your code awaits that task, that exception is re-raised and caught in the catch. At the end of the catch, the code will re-raise that exception (throw;).

How to stop the Parallel for loop process outside the loop?

I start the parallel for loop process from button click(Start Button). The parallel process going well but at the time I moved another page then I return to current parallel process page,process going well.
I try to stop the Parallel process from another button click(button stop). Is it possible?
protected void btnstart_Click(object sender, EventArgs e)
{
try
{
Parallel.For(0, dtrecord.Rows.Count, pOptions1, (j, pls) =>
{
if (Session["Stop"] != null)
{
pls.Stop();
Session.Remove("Stop2");
Session["ParallelStopped"] = 1;
}
else
{
Checkrecords(dtrecord, ImportFileID, j);
}
});
}
catch (Exception ex)
{
Log.Trace("Error occured in btnstop_Click");
Log.Error(ex.Message);
}
}
protected void btnstop_Click(object sender, EventArgs e)
{
try
{
Session["Stop"] = 1;
Session.Remove("start");
Session["start"] = null;
BindImportfileDetails();
BindImportrecordsdetails(hidimid.Value);
bindimportrecords();
Getrecordstatuscount();
Log.Trace("User has been stopping the import process");
}
catch (Exception ex)
{
Log.Trace("Error occured in btnstop_Click");
Log.Error(ex.Message);
}
}

BackgroundWorker doesn't handle exception

I've really read all other similar threads on Stackoverflow. Nothing works for me...
I throw an exception of type "Exception" but i can't handle the exception.
I've tried it in the DoWork Progress, in the CompletedEvent (with try/catch, witch e.error....)
void bgGetResponse_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
ConvertByte(myFile);
myFile= null;
}
}
void bgGetResponse_DoWork(object sender, DoWorkEventArgs e)
{
byte[] test= new byte[] { 1, 1, 0, 1, 1};
//Here the error occured (just with throw new Exception("error"))
//The method only throws an exception (for test purposes)
testResponse= _configManager.GetResponse(test, 0);
}
GetResponse(...)
{
throw new Exception("..!");
}
Any ideas?
Thanks for your efforts
I usually just catch it in the work Method and set the result to it.
private void BGW_DoWork(object sender, DoWorkEventArgs e)
{
...
}
catch (Exception ex)
{
e.Result = ex;
}
Then look in the Completed event,
private void BGW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.Cursor = Cursors.Default;
try
{
Exception ex = e.Result as Exception;
if (null != ex)
throw ex;
...
If by "can't handle" the exception you mean can't use catch, that's true. You just use the Error property. You could "throw" that in your Completed event handler; but then you stack frame will be different.
e.g.:
try
{
if(e.Error != null) throw(e.Error)
// handle success case
}
catch(MyException exception)
{
// handle specific error.
}
Any unhandled exceptions occuring in the BackgroundWorkers DoWork function will cause the worker to fire RunWorkerCompleted where the event argument will contain the error.

How to pass a thrown exception from a C# class to a C# Form

I have a project in c# which is split into UI layer and Business layer.
Basically I have a form where you can select an account and input a number for deposit. Once you click the OK button, your DepositTransaction.cs will handle the transaction.
Here is the sample code for DepositForm:
private void buttonOK_Click(object sender, EventArgs e) {
try {
bool inputTest;
decimal amount;
inputTest = decimal.TryParse(textBoxAmount.Text, out amount);
if (inputTest == false) {
throw new InvalidTransactionAmtException();
} else {
BankAccount account = comboBoxAccount.SelectedItem as BankAccount;
deposit = new DepositTransaction(account, amount);
this.DialogResult = DialogResult.OK;
}
} catch (InvalidTransactionAmtException ex) {
errorProviderDeposit.SetError(textBoxAmount, ex.Message);
textBoxAmount.Select();
textBoxAmount.SelectAll();
} catch (InvalidTransactionAmtNegativeException ex) {
errorProviderDeposit.SetError(textBoxAmount, ex.Message);
textBoxAmount.Select();
textBoxAmount.SelectAll();
} catch (AccountInactiveException ex) {
errorProviderDeposit.SetError(textBoxAmount, ex.Message);
textBoxAmount.Select();
textBoxAmount.SelectAll();
}
}
And now the sample code for the DepositTransaction
public override void DoTransaction() {
try {
if (Amount <= 0) { //Amount is the amount passed by the form
throw new InvalidTransactionAmtNegativeException();
}
if (acc.Active == false) { //acc is the account passed by the form
throw new AccountInactiveException();
}
acc.Credit(Amount);
Summary = string.Format("{0} {1}", Date.ToString("yyyy-MM-dd"), this.TransactionType);
this.setStatus(TransactionStatus.Complete);
} catch (InvalidTransactionAmtNegativeException ex) {
throw;
} catch (AccountInactiveException ex) {
throw;
}
}
However, trying the above, does not pass the error to the Form. It just crashes the program saying that the exception was not handled.
I saw another question on stackoverflow that mentioned the way to pass the error is just to use throw: and that error will be passed to the class that called this class (in my case the form), and it will be handled in the form.
What am I doing wrong?
Thank you
It just means that an exception that is neither of type InvalidTransactionAmtNegativeException nor AccountInactiveException is being thrown. Add new catch block
catch (Exception ex) {
throw;
}
EDIT: You should have it come last. It will catch any other exceptions that might be thrown within your DoTransaction method
You are repeating code in all your catch blocks in the UI, just use a generic catch block:
private void buttonOK_Click(object sender, EventArgs e) {
try {
bool inputTest;
decimal amount;
inputTest = decimal.TryParse(textBoxAmount.Text, out amount);
if (inputTest == false) {
throw new InvalidTransactionAmtException();
} else {
BankAccount account = comboBoxAccount.SelectedItem as BankAccount;
deposit = new DepositTransaction(account, amount);
deposit.DoTransaction();
this.DialogResult = DialogResult.OK;
}
//catch any type of exception here
} catch (Exception ex) {
errorProviderDeposit.SetError(textBoxAmount, ex.Message);
textBoxAmount.Select();
textBoxAmount.SelectAll();
}
}
It Seems that your exception doesn't comes under the specific exception you have given in catch block. So catch generic exception at the end. It is a good practice.

how to throw an exception from a class back to the form that called it

Hello I have a regular WinForm that calls this:
private void childDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
SQL.createTable("childDirectory"); //THIS LINE
}
catch(SystemException ecp)
{
MessageBox.Show(string.Format("An error occurred: {0}", ecp.Message));
}
}
and have a class named "SQL". The C# class cannot throw a messageBox to the user, only Console.WriteLine:
static public void createTable(string tableToCreate)
{
try
{
.
.
.
.
}
catch (SqlException exp)
{
Console.WriteLine("Database not created: " + exp.Message, "Error");
}
}
How can I throw this SqlExecption back in the Form.cs call? Sorry if my wording is wrong, hopefully you can understand what I'm trying to do.
static public void createTable(string tableToCreate)
{
try
{
.
.
.
.
}
catch (SqlException exp)
{
Console.WriteLine("Database not created: " + exp.Message, "Error");
throw exp;
}
}
And catch it with:
private void childDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
SQL.createTable("childDirectory"); //THIS LINE
}
catch(SystemException ecp)
{
MessageBox.Show(string.Format("An error occurred: {0}", ecp.Message));
}
catch (SqlException exp)
{
}
}
But unless it is necessary you don't need to catch exception in called method if you catch it in calling method.
Since you want to bubble up the exception I would suggest you simply don't catch it in the createTable method - instead add an exception handler for SqlException iny your childDirectoryToolStripMenuItem_Click method.
private void childDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
SQL.createTable("childDirectory"); //THIS LINE
}
catch (SqlException ex)
{
MessageBox.Show("Database not created: " + ex.Message);
}
catch(SystemException ecp)
{
MessageBox.Show(string.Format("An error occurred: {0}", ecp.Message));
}
}
Why not just let the error propogate up to the windows form, and avoid a double catch? You could do the logging there.
However, if you do indeed want to do it this way, then you would just call throw. This will simply rethrow the exception. The plus to this method over throw exp is that it will keep the original stack trace, and not mislead any debugging. An already vetted explanation for this can be found at: What is the proper way to re-throw an exception in C#?

Categories