C# 试图用秒表包装一个函数

标签 c# stopwatch

我一直在尝试查看函数在我的代码中执行需要多长时间,以了解我可以优化的地方。现在我使用一个辅助类,它本质上是一个带有消息的秒表来检查这些。这样做的目的是我应该能够在帮助程序中包装我想要的任何方法调用,并且我会得到它的持续时间。

public class StopwatcherData
{
    public long Time { get; set; }
    public string Message { get; set; }

    public StopwatcherData(long time, string message)
    {
        Time = time;
        Message = message;
    }
}

public class Stopwatcher
{
    public delegate void CompletedCallBack(string result);

    public static List<StopwatcherData> Data { get; set; }
    private static Stopwatch stopwatch { get; set;}

    public Stopwatcher()
    {
        Data = new List<StopwatcherData>();
        stopwatch = new Stopwatch();
        stopwatch.Start();
    }

    public static void Click(string message)
    {
        Data.Add(new StopwatcherData(stopwatch.ElapsedMilliseconds, message));
    }

    public static void Reset()
    {
        stopwatch.Reset();
        stopwatch.Start();
    }
}

现在要使用它,我必须在我想要的函数之前调用 Reset,以便重新启动计时器,然后在它之后调用 click。

Stopwatcher.Reset()
MyFunction();
Stopwatcher.Click("MyFunction");

我已经阅读了一些关于委托(delegate)和操作的内容,但我不确定如何将它们应用于这种情况。理想情况下,我会将该函数作为 Stopwatcher 调用的一部分进行传递。

//End Goal:
Stopwatcher.Track(MyFunction(), "MyFunction Time");

欢迎任何帮助。

最佳答案

这样分析您的应用程序并不是一个好主意,但如果您坚持,您至少可以做出一些改进。

首先,不要重复使用Stopwatch , 只需在每次需要时创建新的即可。

其次,您需要处理两种情况 - 一种是您传递的委托(delegate)返回值,另一种不是。

由于您的 Track方法是静态的 - 使其线程安全是一种常见的做法。非线程安全的静态方法是非常糟糕的主意。为此,您可以将消息存储在线程安全的集合中,例如 ConcurrentBag , 或者只使用 lock每次将项目添加到列表时。

最后你可以得到这样的东西:

public class Stopwatcher {
    private static readonly ConcurrentBag<StopwatcherData> _data = new ConcurrentBag<StopwatcherData>();

    public static void Track(Action action, string message) {
        var w = Stopwatch.StartNew();
        try {
            action();
        }
        finally {
            w.Stop();
            _data.Add(new StopwatcherData(w.ElapsedMilliseconds, message));
        }
    }

    public static T Track<T>(Func<T> func, string message) {
        var w = Stopwatch.StartNew();
        try {
            return func();
        }
        finally {
            w.Stop();
            _data.Add(new StopwatcherData(w.ElapsedMilliseconds, message));
        }
    }
}

然后像这样使用它:

Stopwatcher.Track(() => SomeAction(param1), "test");
bool result = Stopwatcher.Track(() => SomeFunc(param2), "test");

如果您要将其与异步委托(delegate)(返回 TaskTask<T>)一起使用 - 您需要为这种情况再添加两个重载。

关于C# 试图用秒表包装一个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49980907/

相关文章:

c# - 秒表与使用 System.DateTime.Now 计时事件

javascript - 10ms 间隔与 firefox

C# 命令执行期间遇到 fatal error

c# - 如何检查 NavigationContext.QueryString?

ios - swift |计时器不会在无效调用时停止,而是加速?

c# - 我应该在方法结束时停止秒表吗?

c#-4.0 - 如果封闭方法即将返回,我是否需要停止秒表?

c# - 我应该在 c# 变量中添加双引号以在 Razor 中添加 css 类吗?

c# - asp.net中的后台函数

c# - 常规使用 soap 错误的 WCF 客户端的处置