I have following generic method in abstract class which is in many places across application:
protected T Execute<T>(Func<T> func)
{
try
{
return func();
}
catch (InvalidOperationException invalidEx)
{
throw new InvalidException(invalidEx.Message, invalidEx);
}
catch (SqlException sqlEx)
{
throw new DbException(sqlEx.Message, sqlEx, ConvertSQLError(sqlEx));
}
}
It is in a base class and all derived classes use this one above in order to execute delegate Func. Calling code looks something like this:
public int SomeMethodInDerivedClass(.....){
result = Execute(() =>
{....code ommited becouse of clarity })
}
What would be the best way to
- Rewrite this method to be able to call it in an async way
- Use await efficiently in calling code?
What I would like to achieve, actualy to be able to rewrite SomeMethodInDerivedClass so that it can return Task instead of int? Where should I start from?
Thank you in advance
CodePudding user response:
I think you can add another method for your async Func:
protected async Task<T> ExecuteAsync<T>(Func<Task<T>> func)
{
try
{
return await func();
}
catch (InvalidOperationException)
{
throw;
}
catch (SqlException)
{
throw;
}
}
If you want rethrow an exception, use previous code instead of create another exception because you lose the original exception context when you create a new one.
CodePudding user response:
async
await
is like zombie curse, it will contaminate entire codebase. It's not that bad however.
Yes, to use efficiently async
await
, you need to return Task<T>
. So in your example would be Task<int>
.
However is the delegate an asynchronous operation? If not you need to make it behave as one, so you need to wrap it into a Task.
It's quiet difficult to give you exact steps, as like I said, it should contaminate up to main, so everything operate on async
await
and Task
, for the code to really benefit from the pattern.
CodePudding user response:
So in the end I acome up with following solution:
protected async Task<T> ExecuteAsync<T>(Func<T> func)
{
try
{
return await Task.Run(func);
}
And calling code is like this one:
public async Task<int> SomeMethod(......)
{
result = await ExecuteAsync(() =>
{
....code ommited for brevity
}
}