Abort process when Exception c# - c#

I have a function which has multiple function calls
public async Task Initializer()
{
try
{
await _inject.UpdateFunction();
await _inject.AccountUpdate();
await _inject.InsertData(Args);
}
catch (Exception ex)
{
_logger.Error(" Error:{ex.Message} | {ex.StackTrace}");
throw;
}
}
Here If 1st method calls gets any exception, need to log exception . So decorated with try catch block. I have some parallel calls to other methods inside UpdateFunction
public async Task UpdateFunction()
{
try
{
string sql = "SELECT somedata FROM tblData WHERE deptid = 'Fun-10'";
var lstData = await _dataAccess.QueryAsync<string>(sql);
using SemaphoreSlim maxThread = new SemaphoreSlim(5);
var tasks = lstData.Select(async data =>
{
try
{
await maxThread.WaitAsync();
await GetIds(data);
}
catch (Exception ex)
{
_logger.Error($"Error : {ex.Message} | {ex.StackTrace}");
}
finally
{
maxThread.Release();
}
});
await Task.WhenAll(tasks);
}
catch (Exception ex)
{
_logger.Error($"Error : {ex.Message} | {ex.StackTrace}");
}
}
In this case I got some exception in GetIds(), which is decorated by try catch .
If any of the method throws exception, I need to abort Initializer(). I added try catch in
before tasks and tried,currently inside task added try catch, still not able to abort Initializer().

You can add throw inside the catch block of the UpdateFunction method:
catch (Exception ex)
{
_logger.Error($"Error : {ex.Message} | {ex.StackTrace}");
throw;
}
This way the error will be propagated to the caller of the method.

Related

ASP.NET Core Web API try catch exception question

In my API, I have over 25 API controllers, in every controller, using the following code to catch exception, I think it is too many code here, any good suggestion for the structure, thanks.
try
{
*code here*
}
catch (UnauthorizedAccessException ex)
{
}
catch (BadRequestException ex)
{
}
catch (HttpRequestException ex)
{
}
catch (TimeoutRejectedException ex)
{
}
catch (FileNotFoundException ex)
{
}
catch (SqlException ex)
{
}
catch (ValidationException ex)
{
}
catch (Exception ex)
{
}
Any simple way to do that.
IF
you plan to handle each exception separately - your approach is the way to go. I suggest to use this "ugly" code simply because it is more readable. If all your exceptions have common handling (for example logging) - you can use only catch (Exception e) and call your logging methods. This will work for all types of exceptions.
OR
If you decide that some of your exceptions might have common handling - you can go with:
try
{
// do
}
catch (Exception e)
{
if (e is BadRequestException ||
e is HttpRequestException ||
e is TimeoutRejectedException )
{
// Log exception
}
}
OR
A good approach is to use a delegate for exception handling. Since you're going to log exceptions, the delegate will handle this.
Action<Exception> HandleError = (e) => {
// Log exception
};
catch (UnauthorizedAccessException e) { HandleError(e); }
catch (BadRequestException e) { HandleError(e); }
catch (HttpRequestException e) { HandleError(e); }
OR
You can combine the first and the second approach
if (e is BadRequestException ||
e is HttpRequestException ||
e is TimeoutRejectedException )
{
HandleError(e);
}

How to get exception code in C# catch block

In the try catch block want to get the catch exception code, we know that 404: not found, 400: bad request. In my catch block want to get exception code. How to get exception code in C# catch block.
try
{
await next(context);
}
catch (Exception ex)
{
}
You can just catch the WebException, and then, check the ProtocolError and status code.
}
catch(WebException e) {
if(e.Status == WebExceptionStatus.ProtocolError) {
Console.WriteLine("Status Code : {0}", ((HttpWebResponse)e.Response).StatusCode);
Console.WriteLine("Status Description : {0}", ((HttpWebResponse)e.Response).StatusDescription);
}
}
catch(Exception e)
{
//
}

Exception Handiling in Independent functions, without stoping the C# Console Application

I am working on C# console application.
Want to impliment "Exception Handling".
Below are the code of ConsoleApp.
static public void Main(string[] args)
{
try
{
for (int i = 0; i < 10; i++)
{
ONE_IndependentProcess(i);
}
TWO_IndependentProcess();
THR_IndependentProcess();
}
catch (System.TimeoutException ex)
{
Console.WriteLine("System.TimeoutException");
}
catch (System.Exception ex)
{
Console.WriteLine("System.Exception");
}
finally
{
Console.WriteLine("End.");
}
}
If an error occurs in TWO_IndependentProcess... application stops, without executing the THR_IndependentProcess
#1. In this case i want THR_IndependentProcess to be execute, and write a Exception Error Information of TWO_IndependentProcess in the Console.
If an error occurs in the ONE_IndependentProcess(3) (in 3rd iteration) application stops, without executing the: remaining iteration(4 to 9), TWO_IndependentProcess & THR_IndependentProcess
#2. In this case also i want the app to execute all, and just write a Exception Error Information of ONE_IndependentProcess(3) in the Console.
Note: I have four Catch block with Detail Exception Information and i want to apply all these four catch block in all three IndependentProcess function.
I would recommend you keep just one copy of your error handling logic and make use of lambda functions to wrap the calls with it:
static private void WithCatch(Action f)
{
try
{
f();
}
catch (System.TimeoutException ex)
{
Console.WriteLine("System.TimeoutException");
}
catch (System.Exception ex)
{
Console.WriteLine("System.Exception");
}
}
static public void Main(string[] args)
{
WithCatch(() => {
for (int i = 0; i < 10; i++)
ONE_IndependentProcess(i);
});
// You could also do this inside the for loop for each one if you want
// to attempt all 10 even if one fails:
//for (int i = 0; i < 10; i++)
// WithCatch(() => {ONE_IndependentProcess(i);});
WithCatch(() => {TWO_IndependentProcess();});
WithCatch(() => {THR_IndependentProcess();});
}
You need to move each independent process into a separate try/catch block.
e.g.
static public void Main(string[] args)
{
try
{
for (int i = 0; i < 10; i++)
{
ONE_IndependentProcess(i);
}
}
catch (System.TimeoutException ex)
{
Console.WriteLine("System.TimeoutException");
}
catch (System.Exception ex)
{
Console.WriteLine("System.Exception");
}
finally
{
Console.WriteLine("End.");
}
try
{
TWO_IndependentProcess();
}
catch (System.TimeoutException ex)
{
Console.WriteLine("System.TimeoutException");
}
catch (System.Exception ex)
{
Console.WriteLine("System.Exception");
}
finally
{
Console.WriteLine("End.");
}
try
{
THR_IndependentProcess();
}
catch (System.TimeoutException ex)
{
Console.WriteLine("System.TimeoutException");
}
catch (System.Exception ex)
{
Console.WriteLine("System.Exception");
}
finally
{
Console.WriteLine("End.");
}
}
You will have to use catch blocks within independent functions/process and deal with the exception within that catch block. This way you can allow program execution to continue without terminating.
try using generic functions to record exceptions - that way you can reuse this function within different catch blocks.

Looking for an elegant way to get around "Cannot await in the body of a finally clause"

I have the following function:
private async Task DoSomething(NamespaceConnectionInfo nci)
{
var session = await m_sessionProvider.GetSessionAsync(nci);
SomeLegacySynchronousCode(session);
await m_sessionProvider.EndSessionAsync(session);
}
where EndSessionAsync logs and swallows any exception (like a good destructor).
The problem is that SomeLegacySynchronousCode may throw an exception and then the session leaks.
It is clear to me perfectly why the following code is illegal:
private async Task DoSomething(NamespaceConnectionInfo nci)
{
var session = await m_sessionProvider.GetSessionAsync(nci);
try
{
SomeLegacySynchronousCode(session);
}
finally
{
await m_sessionProvider.EndSessionAsync(session);
}
}
So, I am looking for an alternative that would be both correct and elegant.
Variant I
private async Task DoSomething(NamespaceConnectionInfo nci)
{
var session = await m_sessionProvider.GetSessionAsync(nci);
Exception exc = null;
try
{
SomeLegacySynchronousCode(session);
}
catch (Exception e)
{
exc = e;
}
await m_sessionProvider.EndSessionAsync(session);
if (exc != null)
{
// Wrap to preserve the original stack trace.
throw new AggregateException(exc);
}
}
Variant II
private Task DoSomething(NamespaceConnectionInfo nci)
{
return m_sessionProvider.GetSessionAsync(nci).ContinueWith(t =>
{
Task result = null;
try
{
SomeLegacySynchronousCode(t.Result);
}
finally
{
if (t.Exception == null)
{
result = m_sessionProvider.EndSessionAsync(t.Result);
}
}
return result;
}).Unwrap();
}
Neither are as elegant as the aforementioned illegal async/await version.
I am looking to improve over the two variants that I have proposed, because both are ugly, frankly.
Any ideas?
The commonly-accepted answer appears to be similar to your Variation 1:
You can move the logic outside of the catch block and rethrow the
exception after, if needed, by using ExceptionDispatchInfo.
static async Task f()
{
ExceptionDispatchInfo capturedException = null;
try
{
await TaskThatFails();
}
catch (MyException ex)
{
capturedException = ExceptionDispatchInfo.Capture(ex);
}
if (capturedException != null)
{
await ExceptionHandler();
capturedException.Throw();
}
}
This way, when the caller inspects the exception's StackTrace
property, it still records where inside TaskThatFails it was thrown.

Can I not catch a specific or custom exception?

I dont want to catch some exception. Can I do it somehow?
Can I say something like this:
catch (Exception e BUT not CustomExceptionA)
{
}
?
try
{
// Explosive code
}
catch (CustomExceptionA){ throw; }
catch (Exception ex)
{
//classic error handling
}
try
{
}
catch (Exception ex)
{
if (ex is CustomExceptionA)
{
throw;
}
else
{
// handle
}
}
Starting with C# 6, you can use an exception filter:
try
{
// Do work
}
catch (Exception e) when (!(e is CustomExceptionA))
{
// Catch anything but CustomExceptionA
}
You can filter it:
if (e is CustomExceptionA) throw;
And of course you can catch it and rethrow it:
try
{
}
catch (CustomExceptionA) { throw; }
catch (Exception ex) { ... }
First off, it's bad practice to catch Exception unless you log and re-throw it. But if you must, you need to catch your custom exception and re-throw it like so:
try
{
}
catch (CustomExceptionA custome)
{
throw custome;
}
catch (Exception e)
{
// Do something that hopefully re-throw's e
}
After being schooled by #Servy in the comments, I thought of a solution that'll let you do [what I think] you want to do. Let's create a method IgnoreExceptionsFor() that looks like this:
public void PreventExceptionsFor(Action actionToRun())
{
try
{
actionToRun();
}
catch
{}
}
This can then be called like this:
try
{
//lots of other stuff
PreventExceptionsFor(() => MethodThatCausesTheExceptionYouWantToIgnore());
//other stuff
}
catch(Exception e)
{
//do whatever
}
That way, every line except for the one with PreventExceptionsFor() will throw exceptions normally, while the one inside PreventExceptionsFor() will get quietly passed over.

Categories

Resources