为函数计算包装类的时间的最佳方法是什么?

时间:2017-04-09 14:01:35

标签: c# asp.net .net async-await stopwatch

我想开始测量函数在多个位置的程序中运行所花费的时间。

在代码中处理StopWatch似乎有点乱,所以我决定把它包起来。

这些是我需要的东西:

  • 该函数将接收可能有或没有返回值的异步函数
  • 我需要退出函数两件事:返回值(如果存在)和以秒为单位运行的时间

我希望找到一个可读且可持续的解决方案,因为它将用于多个项目。

这是我到目前为止所做的:

public class TimeMeasurer 
{
private readonly Stopwatch _stopWatch;

public TimeMeasurer()
{
    _stopWatch = new Stopwatch();
}

public async Task<Tuple<double, TReturn>> Start<TReturn>(Func<Task<TReturn>> function)
{
    try
    {
        _stopWatch.Start();
        var val = await function();
        var took = _stopWatch.Elapsed.TotalSeconds;

        return Tuple.Create(took, val);
    }
    finally
    {
        _stopWatch.Stop();
        _stopWatch.Reset();
    }
}

public async Task<double> Start(Func<Task> function)
{
    try
    {
        _stopWatch.Start();
        await function();
        var took = _stopWatch.Elapsed.TotalSeconds;

        return took;
    }
    finally
    {
        _stopWatch.Stop();
        _stopWatch.Reset();
    }
}
}

如果没有更好的解决方案..

  • 有没有办法合并这两个功能? (一个包含返回值,第二个包含void函数)
  • 有没有办法让某些东西比元组更清晰?我发现处理
  • 有点麻烦

编辑:调用我制作的课程也看起来不太好..

var tuple = await _timeMeasurer.Start(async () => await function(param1, param2));
编辑:我决定提出这个想法。它太乱了。最后我使用StopWatch

1 个答案:

答案 0 :(得分:0)

关于你的第一点,没有太多你可以做的可以组合这些功能,没有太多的逻辑可以结合。

对于你的第二点,我会制作两个自定义类来保存结果。您可以获得幻想并执行一些继承并返回整个任务对象而不仅仅是结果,以防有人想要查看返回任务的某些属性。

最后,没有理由你的函数应该是一个实例,整个类可以是静态的。

以下是我建议进行更改的示例。

public class TimeMeasurerResult
{
    protected readonly Task _task;
    private readonly TimeSpan _duration;

    public TimeMeasurerResult(Task task, TimeSpan duration)
    {
        _task = task;
        _duration = duration;
    }

    public Task Task {get { return _task;}}
    public TimeSpan Duration {get {return _duration;}}
}

public class TimeMeasurerResult<T> : TimeMeasurerResult
{    
    public TimeMeasurerResult(Task<T> task, TimeSpan duration)
        :base(task, duration)
    {
    }

    public T Result {get { return ((Task<T>)_task).Result;}}
}

public static class TimeMeasurer 
{    
    public static async Task<TimeMeasurerResult<TReturn>> Start<TReturn>(Func<Task<TReturn>> function)
    {
        var stopWatch = Stopwatch.StartNew();
        var task = function();
        await task;
        var took = stopWatch.Elapsed;

        return new TimeMeasurerResult<TReturn>(task, took);
    }

    public static async Task<TimeMeasurerResult> Start(Func<Task> function)
    {
        var stopWatch = Stopwatch.StartNew();
        var task = function();
        await task;
        var took = stopWatch.Elapsed;

        return new TimeMeasurerResult(task, took);
    }    
}

以下是using it的示例,请注意我只需var results = await TimeMeasurer.Start(() => Function(a,b));而不是var results = await TimeMeasurer.Start(async () => await Function(a,b));

public class Program
{
    public static void Main()
    {
        AsyncMain().Wait();
    }

    public static async Task AsyncMain()
    {
        int a = 500;
        int b = 10;
        var results = await TimeMeasurer.Start(() => Function(a,b));
        Console.WriteLine("Waited: {0}", results.Duration.TotalSeconds);
        Console.WriteLine("Result: {0}", results.Result);
    }

    public static async Task<int> Function(int a, int b)
    {
        var total = a + b;
        await Task.Delay(total);
        return total;
    }
}