'Convert generic method as async
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
Solution 1:[1]
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.
Solution 2:[2]
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.
Solution 3:[3]
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
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Victor |
| Solution 2 | MikolajR |
| Solution 3 | Branimir Bzeni? |
