简体   繁体   中英

Async version of a method wrapper

I have a couple of methods that are provided to me by an API. I wish to write a handy helper to log the execution time of said methods, and any chunk of code in general.

Use case methods would typically look like this :

object       GetData(string statementKey, string parametersJson, out string errorMessage);
Task<object> GetDataAsync(string statementKey, string parametersJson, CancellationToken cancellationToken = default(CancellationToken));

I wrote a method wrapper for the sync method :

public static T With<T>(string message, Func<T> func)
{
    var watch = new Stopwatch();

    T returned;

    watch.Start();
    try
    {
        returned = func.Invoke();
    }
    catch (Exception exception)
    {
        Log.Logger.Error(exception, $"Error in {message}");
        throw;
    }
    finally
    {
        watch.Stop();
    }

    // Logging logic here

    return returned;
}

(I am aware this doesn't work with void methods, but an Action overload is trivial if action is sync).

Now if the passed method is Async, I would measure inaccurate execution times. I am a bit confused about how would I need to change the method above to work with async methods.

I tried this implementation but it feels wrong.

public static async Task<T> AsyncWith<T>(string message, Func<Task<T>> func)
{
    T returned;


    try
    {
        var watch = new Stopwatch();
        watch.Start();
        returned = await func.Invoke().ConfigureAwait(false);
        watch.Stop();
        // Logging logic here
    }
    catch (Exception exception)
    {
        Log.Logger.Error(exception, $"Error in {message}");
        throw;
    }

    return returned;
}

Shouldn't I start a task actually ? I don't understand why it is compiling with T returned instead of Task<T> returned

I tried this implementation but it feels wrong.

Your implementation is correct.

Shouldn't I start a task actually ?

Methods return their tasks "hot" - ie, running. So calling func.Invoke() is sufficient to start the task.

I don't understand why it is compiling with T returned instead of Task returned

Because the async keyword handles creating the Task<T> wrapper for you, and converts return statements (or exceptions) into logic that completes the Task<T> .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM