从指定时间开始计时
本文关键字:开始 定时间 | 更新日期: 2023-09-27 18:22:25
我试图从给定的时间(从数据库中提取的十进制值)启动秒表。然而,由于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();
你知道我该怎么做吗?干杯
正常的StopWatch
不支持偏移时间跨度的初始化,而TimeSpan
是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
StopWatch
的Elapsed
属性是只读的,这是有意义的。秒表只是测量从开始到停止之间经过的时间。
如果要将时间跨度添加到值中,请获取变量中的Elapsed
值,并在测量后(即停止后)向其添加时间跨度。
我认为您希望在TimeSpan
指定的一定时间后启动Stopwatch
。我想知道为什么您不想在DateTime
指定的时间启动Stopwatch
?
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);
这不太适合OP场景(我猜他们8年前就解决了这个问题),但如果你只需要为单元测试或其他非生产场景创建秒表,那么你可以使用反射来修改经过的时间。
这不会给你最好的性能,如果Stopwatch的底层实现发生变化,可能会中断,所以我会非常谨慎地使用这种方法。
然而,对于需要绕过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;
}
}
如果将此文件添加到项目中,则项目中不需要更改任何内容。该类继承自原始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; }
}
}