Just for completeness, I want to show you how the simpler code (second solution) from the accepted answer could return a negative value, as noted in that answer.
This thought-experiment uses two threads, designated T1 and T2. I'm prefixing the stack variables with T1 and T2 so you can tell them apart (below).
Let's assume that lastTimeStamp starts at 900 and the current time is 1000.
Now consider the following interlaced thread operations:
T1: long currentTimestamp = Stopwatch.GetTimestamp();
=> T1:currentTimeStamp = 1000
T2: long currentTimestamp = Stopwatch.GetTimestamp();
=> T2:currentTimeStamp = 1010
T2: var previous = Interlocked.Exchange(ref lastTimestamp, T2:currentTimestamp);
=> T2:previous = 900, lastTimestamp = 1010
T1: var previous = Interlocked.Exchange(ref lastTimestamp, T1:currentTimestamp);
=> T1:previous = 1010, lastTimestamp = 1000
T1: var ticks = (T1:currentTimestamp - T1:previous)
=> ticks = 1000 - 1010 = -10
T2: var ticks = (T2:currentTimestamp - T2:previous)
=> ticks = 1010 - 900 = 110
As you can see, thread T1 will end up returning -10.
[Addendum]
Here's my take on it - I'm not bothering to convert the stopwatch timestamp to a TimeSpan; I'm just leaving it in the units returned from Stopwatch.GetTimestamp()
for brevity (and it will be slightly quicker):
public static long Span()
{
long previous;
long current;
do
{
previous = lastTimestamp;
current = Stopwatch.GetTimestamp();
}
while (previous != Interlocked.CompareExchange(ref lastTimestamp, current, previous));
return current - previous;
}
static long lastTimestamp = Stopwatch.GetTimestamp();
This is the same solution as the accepted answer above, just organised slightly differently.