Reputation: 183
I want to do 4 actions and each one can throw an exception. I need to execute them all and log all errors that happened along the way
I can do it in a big and clumsy way :
var exceptions = new List<ExceptionType1>();
try {
result1 = await action1();
} catch (ExceptionType1 ex1) {
exceptions.Add(ex1);
logger.Log(ex1);
}
try {
result2 = await action2();
} catch (ExceptionType1 ex1) {
exceptions.Add(ex1);
logger.Log(ex1);
}
try {
result3 = await action3(result1);
} catch (ExceptionType2 ex2) {
var ex1 = new ExceptionType1(ex2);
exceptions.Add(ex1);
logger.Log(ex1);
}
try {
result4 = await action4(result2);
} catch (ExceptionType2 ex2) {
var ex1 = new ExceptionType1(ex2);
exceptions.Add(ex1);
logger.Log(ex1);
}
if (exceptions.Count > 0) {
return false;
}
Obviously sometimes things like that bloat in size quickly I would like to do it in more elegant way :
var exceptions = new List<ExceptionType1>();
try {
result1 = await action1();
result2 = await action2();
result3 = await action3(result1);
result4 = await action4(result2);
} catch(Exception ex) {
var ex1 = new ExceptionType1(ex);
exceptions.Add(ex1);
logger.Log(ex1);
???
~~Goto try block and continue executing~~
???
}
if (exceptions.Count > 0) {
return false;
}
I tried to find info how to get back into try block and continue executing but was unsuccessfull. Is it possible. Is there any other way around the problem that I didn't consider?
Upvotes: 2
Views: 615
Reputation: 11
I think WhenAll() method for Task will suit your purpose: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-catch#taskwhenall-example First of all, your actions are already async. Moreover, you can divide to several WhenAll() blocks if you need to follow any order of execution
Example from docs:
public async Task action1()
{
throw new InvalidOperationException();
}
public async Task action2()
{
throw new NotImplementedException();
}
public async Task action3()
{
throw new InvalidCastException();
}
public async Task DoMultipleAsync()
{
Task theTask1 = action1();
Task theTask2 = action2();
Task theTask3 = action3();
Task allTasks = Task.WhenAll(theTask1, theTask2, theTask3);
try
{
await allTasks;
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex.Message);
Console.WriteLine("Task IsFaulted: " + allTasks.IsFaulted);
foreach (var inEx in allTasks.Exception.InnerExceptions)
{
Console.WriteLine("Task Inner Exception: " + inEx.Message);
}
}
}
// Output:
// Exception: Operation is not valid due to the current state of the object.
// Task IsFaulted: True
// Task Inner Exception: Operation is not valid due to the current state of the object.
// Task Inner Exception: The method or operation is not implemented.
// Task Inner Exception: Specified cast is not valid.
Upvotes: 1
Reputation: 26432
how to get back into try block and continue executing.. Is it possible?
You can't do what you are looking for: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-catch
The block is executed until an exception is thrown or it is completed successfully.
Once out of the block, even the variables that have been initialized are rolled back.
It's the whole point of the exception to stop the execution of the safe guarded code.
Upvotes: 1
Reputation: 272770
Maybe you can extract this into a local function:
// declare this inside the method that contains the code you showed
async void GetResult<TResult, TException>(out TResult result, Func<Task<TResul>> resultGetter, Func<TException, ExceptionType1> mapper)
where TException: Exception {
try {
result = await resultGetter();
} catch (TException ex) {
var ex1 = mapper(ex)
exceptions.Add(ex1);
logger.Log(ex1);
}
}
Callers:
GetResult(out result1, action1, (ExceptionType1 e) => e);
GetResult(out result2, action2, (ExceptionType1 e) => e);
GetResult(out result3, async () => await action3(result1), (ExceptionType2 e) => new ExceptionType1(e));
GetResult(out result4, async () => await action4(result2), (ExceptionType2 e) => new ExceptionType1(e));
Upvotes: 2
Reputation: 81523
One way I guess (given your reequipments) is to create a local method
var exceptions = new List<Exception>();
async Task<T> DoAsync<T>(Func<Task<T>> func)
{
try
{
return await func();
}
catch (Exception ex)
{
exceptions.Add(ex);
logger.Log(ex);
}
return default;
}
result1 = await DoAsync(action1);
result2 = await DoAsync(action2);
if (exceptions.Count > 0)
{
return false;
}
Upvotes: 2