Home > Mobile >  Convert generic method as async
Convert generic method as async

Time:04-11

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

  1. Rewrite this method to be able to call it in an async way
  2. 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 
            }
    }
  • Related