Reputation: 142
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
Upvotes: 0
Views: 340
Reputation: 456417
I tried this implementation but it feels wrong.
Your implementation is correct.
Shouldn't I start a task actually ?
Methods return their tasks "hot" - i.e., 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>
.
Upvotes: 1