6

我试图从给定时间开始秒表(从数据库中提取的十进制值)。但是,由于Stopwatch.Elapsed.Add返回一个新的Timespan而不是修改Stopwatch,我无法找到最好的前进方式。

var offsetTimeStamp = new System.TimeSpan(0,0,0).Add(TimeSpan.FromSeconds((double)jd.ActualTime));
Stopwatch.Elapsed.Add(offsetTimeStamp);
Stopwatch.Start();

任何想法我怎么能做到这一点?干杯

4

5 回答 5

7

法线StopWatch不支持具有偏移时间跨度的初始化,并且TimeSpan是 a struct,因此Elapsed是不可变的。你可以写一个包装器StopWatch

public class StopWatchWithOffset
{
    private Stopwatch _stopwatch = null;
    TimeSpan _offsetTimeSpan;

    public StopWatchWithOffset(TimeSpan offsetElapsedTimeSpan)
    {
        _offsetTimeSpan = offsetElapsedTimeSpan;
        _stopwatch = new Stopwatch();
    }

    public void Start()
    {
        _stopwatch.Start();
    }

    public void Stop()
    {
        _stopwatch.Stop();
    }

    public TimeSpan ElapsedTimeSpan
    {
        get
        {
            return _stopwatch.Elapsed + _offsetTimeSpan;
        }
        set
        {
            _offsetTimeSpan = value;
        }
    }
}

现在您可以添加开始时间跨度:

var offsetTimeStamp = TimeSpan.FromHours(1);
var watch = new StopWatchWithOffset(offsetTimeStamp);
watch.Start();
System.Threading.Thread.Sleep(300); 
Console.WriteLine(watch.ElapsedTimeSpan);// 01:00:00.2995983
于 2013-07-16T09:36:00.263 回答
0

Elapsed属性StopWatch是只读的,这是有道理的。秒表只是测量开始和停止之间经过的时间量。

如果您想为该值添加时间跨度 -Elapsed在您测量后(即停止后),获取变量中的值并为其添加时间跨度。

于 2013-07-16T09:29:17.570 回答
0

我认为你想Stopwatch在 a 指定的一定时间后开始你的TimeSpan。我想知道为什么你不想Stopwatch在 a 指定的时间开始你的DateTime

public class MyStopwatch : Stopwatch
{
    public void Start(long afterMiliseconds)
    {
        Timer t = new Timer() { Interval = 1 };
        int i = 0;
        t.Tick += (s, e) =>
        {
            if (i++ == afterMiliseconds)
            {
                Start();
                t.Stop();
            }
        };
        t.Start();
    }
}
//use it
var offsetTimeStamp = new System.TimeSpan(0,0,0).Add(TimeSpan.FromSeconds((double)jd.ActualTime));
myStopwatch.Start((long)offsetTimeStamp.TotalMiliseconds);
于 2013-07-16T09:38:07.240 回答
0

如果将此文件添加到项目中,则项目中无需更改任何内容。该类继承自原始Stopwatch类,具有相同的名称和相同的方法/属性,但具有附加功能:

  • SetOffset()方法
  • 用偏移量初始化

.

using System;

public class Stopwatch : System.Diagnostics.Stopwatch
{
    TimeSpan _offset = new TimeSpan();

    public Stopwatch()
    {
    }

    public Stopwatch(TimeSpan offset)
    {
        _offset = offset;
    }

    public void SetOffset(TimeSpan offsetElapsedTimeSpan)
    {
        _offset = offsetElapsedTimeSpan;
    }

    public TimeSpan Elapsed
    {
        get{ return base.Elapsed + _offset; }
        set{ _offset = value; }
    }

    public long ElapsedMilliseconds
    {
        get { return base.ElapsedMilliseconds + _offset.Milliseconds; }
    }

    public long ElapsedTicks
    {
        get { return base.ElapsedTicks + _offset.Ticks; }
    }

}
于 2017-02-26T08:59:01.923 回答
0

这不太适合 OPs 场景(我猜他们在 8 年前解决了这个问题),但是如果您只需要为单元测试或其他非生产场景创建秒表,那么您可以使用反射来修改经过的时间。

这不会为您提供最佳性能,并且如果 Stopwatch 的底层实现发生更改可能会中断,因此我会非常谨慎地使用这种方法。

但是,对于需要传递秒表并且无法更改以使用替代实现的单元测试,我发现这种方法运行良好并且风险是可以接受的。

/// <summary>
/// Some static mechanisms for creating Stopwatch instances that start from a specific time.
/// </summary>
public static class TestStopwatch
{
    /// <summary>
    /// Creates a <see cref="Stopwatch"/> instance with a specified amount of time already elapsed
    /// </summary>
    /// <param name="start">The <see cref="TimeSpan"/> indicated the elapsed time to start from.</param>
    public static Stopwatch WithElapsed(TimeSpan start)
    {
        var sw = new Stopwatch();

        var elapsedProperty = typeof(Stopwatch).GetField("_elapsed", BindingFlags.NonPublic | BindingFlags.Instance);

        long rawElapsedTicks = start.Ticks;

        if (Stopwatch.IsHighResolution)
        {
            rawElapsedTicks = (long)((double)rawElapsedTicks / (10000000 / (double)Stopwatch.Frequency));
        }

        elapsedProperty.SetValue(sw, rawElapsedTicks);

        return sw;
    }

    /// <summary>
    /// Initializes a new <see cref="Stopwatch"/> instance, sets the elapsed time property to the specified value,
    /// and starts measuring elapsed time.
    /// </summary>
    /// <param name="start">The <see cref="TimeSpan"/> indicated the elapsed time to start from.</param>
    public static Stopwatch StartNew(TimeSpan start)
    {
        var sw = TestStopwatch.WithElapsed(start);
        sw.Start();
        return sw;
    }
}
于 2021-08-15T21:54:50.897 回答