C#试图用秒表包裹一个功能

Bla*_*dud 5 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Stopwatcher.Reset()
MyFunction();
Stopwatcher.Click("MyFunction");
Run Code Online (Sandbox Code Playgroud)

我已经阅读了一些关于代表和行动的内容,但我不确定如何将它们应用于这种情况.理想情况下,我会将该函数作为Stopwatcher调用的一部分传递.

//End Goal:
Stopwatcher.Track(MyFunction(), "MyFunction Time");
Run Code Online (Sandbox Code Playgroud)

欢迎任何帮助.

Evk*_*Evk 8

像这样描述你的应用程序并不是一个好主意,但如果你坚持,你至少可以做一些改进。

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

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

由于您的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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

Stopwatcher.Track(() => SomeAction(param1), "test");
bool result = Stopwatcher.Track(() => SomeFunc(param2), "test");
Run Code Online (Sandbox Code Playgroud)

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