9

我正在编写一个非常简单的实用程序类,目的是测量传入的任何方法(任何类型)的执行时间。

在我的情况下Membership.ValidateUser(model.UserName, model.Password),返回布尔所以我得到一个例外。

我想是否可以编写一个这种类型的实用程序类,以及如何修复它的代码示例。使用动态而不是动作有意义吗?

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);
            }
        }
4

4 回答 4

8

您当前的代码尝试执行ValidateUser并将结果用作方法参数。你想在先执行的情况下传递一个动作ValidateUser

您只需将方法调用转换为使用 lambda 表达式来创建委托:

Tracing.Log(() => Membership.ValidateUser(model.UserName, model.Password), 
            "Membership.ValidateUser");

(动态打字根本不会影响这一点。)

请注意,为单个方法执行计时通常会给您带来非常嘈杂的结果,除非它是一个相当长的方法调用。通常要对单个方法进行基准测试,您可能会多次执行该方法,直到您花费相当多的时间执行它。使用Stopwatch帮助,但它并没有超越这样一个事实,即您的方法可能需要很少的滴答声才能完成,如果线程被抢占,这将对结果产生不成比例的影响。

编辑:我假设您想纯粹将其用于基准测试。如果您尝试在实际应用程序中进行此跟踪,您将需要一种侵入性较小的方法。以Mini-MVC-Profiler为例。

于 2013-03-13T12:33:31.077 回答
0

无意冒犯,但你的设计方法对我来说似乎倒退了。我假设您的业务目标更多是关于验证用户而不是计时代码操作。如果这不正确,请忽略我。:)

如果我是你,我会在你的验证中注入一个计时/跟踪类,而不是相反。您可以通过多种方式使用依赖注入(其中一种框架或简单的构造函数注入),并在提供时使用它来进行计时。

高温高压

于 2013-03-13T12:35:57.303 回答
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);
            }
        }
    }
于 2013-03-13T12:36:57.653 回答
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);
        }
    }
}
于 2013-03-13T12:39:40.070 回答