我想开始测量函数在我的程序中的多个位置运行所花费的时间。
处理 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
最佳答案
对于你的第一点,你可以做的不多,可以组合这些功能,只是没有太多的逻辑可以组合。
对于你的第二点,我会创建两个自定义类来保存结果。您也可以想象并进行一些继承,并返回整个任务对象,而不仅仅是结果,以防有人想查看返回任务的某些属性。
最后,你的函数没有理由应该是一个实例,整个类都可以是静态的。
这是一个包含我建议的更改的示例。
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;
}
}
关于c# - 为函数制作时间测量包装类的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43307599/