我正在编写一个非常简单的实用工具类,目的是测量传入的任何方法(任何类型)的执行时间。
在我的情况下Membership.ValidateUser(model.UserName, model.Password)
返回bool,所以我得到一个例外。
我想是否可以编写这种类型的utililty类,以及如何修复它的代码示例。 是否有意义使用动态代替行动?
Tracing.Log(Membership.ValidateUser(model.UserName, model.Password), "Membership.ValidateUser");
public static class Tracing
{
public static void Log(Action action, string message)
{
// Default details for the Log
string sSource = "TRACE";
string sLog = "Application";
// Create the Log
if (!EventLog.SourceExists(sSource))
EventLog.CreateEventSource(sSource, sLog);
// Measure time Elapsed for an Action
Stopwatch stopwatch = Stopwatch.StartNew();
action();
stopwatch.Stop();
TimeSpan timeElapsed = stopwatch.Elapsed;
// Write the Log
EventLog.WriteEntry(sSource, "TIME-ELAPSED: " + timeElapsed .ToString() + message, EventLogEntryType.Warning, 234);
}
}
答案 0 :(得分:8)
您当前的代码尝试执行ValidateUser
并使用结果作为方法参数。您希望传递的动作,而首先执行ValidateUser
。
您只需要转换方法调用以使用lambda表达式来创建委托:
Tracing.Log(() => Membership.ValidateUser(model.UserName, model.Password),
"Membership.ValidateUser");
(动态类型根本不会影响这一点。)
请注意,单个方法执行的计时通常会给您带来非常嘈杂的结果,除非它是一个相当长的方法调用。通常要对您希望多次执行该方法的单个方法进行基准测试,直到您花费相当多的时间执行该方法。使用Stopwatch
有帮助,但它没有超越这样一个事实,即你的方法可能需要很少的滴答来完成,如果线程被抢占,那将对结果产生不成比例的影响。
编辑:我假设你想纯粹用它来进行基准测试。如果您尝试在实际应用程序中执行此跟踪,则需要采用创新性较低的方法。例如,请查看Mini-MVC-Profiler。
答案 1 :(得分:0)
没有违法行为,但你的设计方法似乎落后于我。我假设您的业务目标更多地是关于验证用户而不是计时代码操作。如果这不正确,请忽略我。 :)
如果我是你,我会在你的验证中注入一个计时/跟踪课程,而不是相反。您可以以任意数量的方式使用依赖注入(框架之一或简单的构造函数注入),并使用它来进行计时(如果已提供)。
HTH
答案 2 :(得分:0)
如果你可以修改测量的方法,你可以引入一个类,它将在创建时启动计时器,并在处理时停止它。并且,如果超过某个阈值,它将创建一条日志消息
用法将是:
using(var tm = new TimeMeasurementThreshold(TimeSpan.FromSeconds(1),"Sending mail block",logger)){
// measured code here
}
public class TimeMeasurementThreshold : IDisposable
{
private readonly Logger logger;
private readonly TimeSpan thresholdTime;
private readonly string codeBlockName;
private readonly TimeMeasurement timeMeasurement;
public TimeMeasurementThreshold(TimeSpan thresholdTime, string codeBlockName, Logger logger)
{
this.logger = logger;
this.thresholdTime = thresholdTime;
this.codeBlockName = codeBlockName;
timeMeasurement = new TimeMeasurement();
}
public void Dispose()
{
TimeSpan elapsed = timeMeasurement.Elapsed;
if (elapsed >= thresholdTime)
{
logger.Debug("{0} execution time is {1:N0}ms", codeBlockName, elapsed.TotalMilliseconds);
}
}
}
答案 3 :(得分:0)
您可以轻松使用lambda来分配传递给另一个方法的操作的结果,例如:
using System;
namespace Demo
{
public static class Program
{
private static void Main(string[] args)
{
bool result = false;
Tracing.Log(() =>
{
result = test(""); // Assign to result.
}, "Message");
Console.WriteLine(result);
}
private static bool test(string value)
{
return string.IsNullOrEmpty(value);
}
}
public static class Tracing
{
public static void Log(Action action, string message)
{
action();
Console.WriteLine(message);
}
}
}