admin管理员组

文章数量:1391964

.NET 7 introduced a new method to the System.Diagnostics.Stopwatch type called GetElapsedTime. It is used in conjunction with GetTimestamp:

long start = Stopwatch.GetTimestamp();

await LongRunningTaskAsync();

TimeSpan elapsed = Stopwatch.GetElapsedTime(start);

Console.WriteLine($"Duration: {elapsed}");

Recently I've stumbled upon System.TimeProvider while working on a .NET Framework project. It has pretty much the exact same API as Stopwatch:

long start = TimeProvider.System.GetTimestamp();

await LongRunningTaskAsync();

TimeSpan elapsed = TimeProvider.System.GetElapsedTime(start);

Console.WriteLine($"Duration: {elapsed}");

Stopwatch can simply be substituted by TimeProvider.System and the code looks and functions exactly the same.

Now is there actually any difference between the two? TimeProvider.GetElapsedTime has been around far longer than the Stopwatch equivalent, so it's the only option in e.g. .NET Framework. If it already existed, I ask myself why they would even add the same method to the Stopwatch type in a newer version. Which of these should be used when the decision is possible?

.NET 7 introduced a new method to the System.Diagnostics.Stopwatch type called GetElapsedTime. It is used in conjunction with GetTimestamp:

long start = Stopwatch.GetTimestamp();

await LongRunningTaskAsync();

TimeSpan elapsed = Stopwatch.GetElapsedTime(start);

Console.WriteLine($"Duration: {elapsed}");

Recently I've stumbled upon System.TimeProvider while working on a .NET Framework project. It has pretty much the exact same API as Stopwatch:

long start = TimeProvider.System.GetTimestamp();

await LongRunningTaskAsync();

TimeSpan elapsed = TimeProvider.System.GetElapsedTime(start);

Console.WriteLine($"Duration: {elapsed}");

Stopwatch can simply be substituted by TimeProvider.System and the code looks and functions exactly the same.

Now is there actually any difference between the two? TimeProvider.GetElapsedTime has been around far longer than the Stopwatch equivalent, so it's the only option in e.g. .NET Framework. If it already existed, I ask myself why they would even add the same method to the Stopwatch type in a newer version. Which of these should be used when the decision is possible?

Share Improve this question asked Mar 12 at 14:33 baltermiabaltermia 1,3731 gold badge16 silver badges32 bronze badges 2
  • 4 TimeProvider is an abstraction to help with testing while Stopwatch is an implementation tied to the real time. – Klaus Gütter Commented Mar 12 at 14:41
  • TimeProvider provides time (we often use FakeTimeProvider in testing) which can be any value (for instance, we can set it to 28 Feb 2100), that's why we should use Stopwatch to measure real time intervals. – Dmitrii Bychenko Commented Mar 12 at 15:01
Add a comment  | 

2 Answers 2

Reset to default 4

TimeProvider.GetElapsedTime has been around far longer than the Stopwatch equivalent

That's not true. TimeProvider was introduced with .NET 8. It was also packaged as Microsoft.Bcl.TimeProvider (that also targets .NET Framework) so it can be backported in .NET Framework projects.

There is no difference because both StopWatch's and the default TimeProvider implementations (TimeProvider.System) of GetElapsedTime(long startingTime) are more of convenience methods that are using very old APIs such as Stopwatch.GetTimeStamp() and Stopwatch.Frequency to get you from long to TimeSpan in a consistent and predictable way for your system. The main purpose of using TimeProvider is testability - you can change the underlying methods:

public virtual long TimestampFrequency => Stopwatch.Frequency;

public virtual long GetTimestamp() => Stopwatch.GetTimestamp();

in a fake class like FakeTimeProvider:

Indeed, as Klaus said TimeProvider is an abstract class that you can implement yourself and have it return fake (synthetized) values to aid with testing. That is to avoid having your test sleep for seconds, minutes or even years to test functionality, you instead implement a time provider that acts as though it has slept for that long.

The default implementation (TimeProvider.System) is tied to the real clock and acts the same as Stopwatch. You also have the FakeTimeProvider class that implements just enough to help easily synthetize your own time provider for unit testing.

Also note that the class provides more than just the stopwatch functionality, it also allows creating delay tasks (replacing Task.Delay) and timeout cancellation sources (replacing CancellationTokenSource(TimeSpan)).

本文标签: