Retrieve system uptime using C# - c#

Is there a simple way to get a system's uptime using C#?

public TimeSpan UpTime {
get {
using (var uptime = new PerformanceCounter("System", "System Up Time")) {
uptime.NextValue(); //Call this an extra time before reading its value
return TimeSpan.FromSeconds(uptime.NextValue());
}
}
}

I'm a bit late, but another simple way is to use the GetTickCount64 function, which is available starting with Windows Vista and does not overflow as GetTickCount does:
public static TimeSpan GetUpTime()
{
return TimeSpan.FromMilliseconds(GetTickCount64());
}
[DllImport("kernel32")]
extern static UInt64 GetTickCount64();

System.Environment.TickCount gets the number of milliseconds since the system was restarted.
Beware though that it is an Int32 and will overflow after 24.9 days and will become negative. See the remarks on the MDSN docs.

My machine has an uptime of 58 days 17 hours according to Task Manager. I went through and tried each answer here and the fast ones are off by a little bit (~1-3 minutes roughly, but over 58 days of uptime):
Stopwatch.GetTimeStamp(): 58days 17hours 11minutes 25seconds
~Time to calculate (ms): 6.8413
DllImport GetTickCount64(): 58days 17hours 13minutes 34seconds
~Time to calculate (ms): 0.2192
PerformanceCounter(System, System Up Time): 58days 17hours 14minutes 02seconds
~Time to calculate (ms): 1233.2854
ManagementObject LastBootUpTime: 58days 17hours 14minutes 02seconds
~Time to calculate (ms): 30.0283
The last two, using PerformanceCounter or using ManagementObject, are always within the same second as Windows Task Manager (just have to take my word for it, or try it yourself with the code below). Based on the results I am going to use the ManagementObject LastBootUpTime method because it's drastically faster than the PerformanceCounter but is still perfectly accurate when compared to Task Manager.
Note that I did subtract the current elapsed time from each method before printing the times, but the whole thing takes less than 2 seconds to run so the time shift can't be explained by improperly accounting for execution time anyway. Here's the code I used:
[System.Runtime.InteropServices.DllImport("kernel32")]
extern static UInt64 GetTickCount64();
public static void Main()
{
var start = Stopwatch.StartNew();
var eachStart = Stopwatch.StartNew();
var ticks = Stopwatch.GetTimestamp();
var uptime = ((double)ticks) / Stopwatch.Frequency;
var uptimeTimeSpan = TimeSpan.FromSeconds(uptime);
Console.WriteLine("Stopwatch.GetTimeStamp(): " + uptimeTimeSpan.Subtract(start.Elapsed).ToString(#"dd\d\a\y\s\ hh\h\o\u\r\s\ mm\m\i\n\u\t\e\s\ ss\s\e\c\o\n\d\s"));
Console.WriteLine($"~Time to calculate (ms): {eachStart.Elapsed.TotalMilliseconds}");
eachStart.Restart();
Console.WriteLine("DllImport GetTickCount64(): " + TimeSpan.FromMilliseconds(GetTickCount64()).Subtract(start.Elapsed).ToString(#"dd\d\a\y\s\ hh\h\o\u\r\s\ mm\m\i\n\u\t\e\s\ ss\s\e\c\o\n\d\s"));
Console.WriteLine($"~Time to calculate (ms): {eachStart.Elapsed.TotalMilliseconds}");
eachStart.Restart();
var upTime = new PerformanceCounter("System", "System Up Time");
upTime.NextValue(); //Call this an extra time before reading its value
Console.WriteLine("PerformanceCounter(System, System Up Time): " + TimeSpan.FromSeconds(upTime.NextValue()).Subtract(start.Elapsed).ToString(#"dd\d\a\y\s\ hh\h\o\u\r\s\ mm\m\i\n\u\t\e\s\ ss\s\e\c\o\n\d\s"));
Console.WriteLine($"~Time to calculate (ms): {eachStart.Elapsed.TotalMilliseconds}");
eachStart.Restart();
ManagementObject mo = new ManagementObject(#"\\.\root\cimv2:Win32_OperatingSystem=#");
DateTime lastBootUp = ManagementDateTimeConverter.ToDateTime(mo["LastBootUpTime"].ToString());
Console.WriteLine("ManagementObject LastBootUpTime: " + (DateTime.Now.ToUniversalTime() - lastBootUp.ToUniversalTime()).Subtract(start.Elapsed).ToString(#"dd\d\a\y\s\ hh\h\o\u\r\s\ mm\m\i\n\u\t\e\s\ ss\s\e\c\o\n\d\s"));
Console.WriteLine($"~Time to calculate (ms): {eachStart.Elapsed.TotalMilliseconds}");
}

Precise and bigger than System.Environment.TickCount, not involving OS horrific perf counters, WMI or native calls:
var ticks = Stopwatch.GetTimestamp();
var uptime = ((double)ticks) / Stopwatch.Frequency;
var uptimeSpan = TimeSpan.FromSeconds(uptime);

If you are using a later .NET version (Core 3.0/.NET 5.0 or above), then the Environment class now has a TickCount64 property.
This doesn't suffer from the wrap-around issues of the TickCount property, nor do you have to resort to P/Invoke to get the value.
long tickCountMs = Environment.TickCount64;
var uptime = TimeSpan.FromMilliseconds(tickCountMs);

The simplest and proper way to do this is
public static TimeSpan GetUptime()
{
ManagementObject mo = new ManagementObject(#"\\.\root\cimv2:Win32_OperatingSystem=#");
DateTime lastBootUp = ManagementDateTimeConverter.ToDateTime(mo["LastBootUpTime"].ToString());
return DateTime.Now.ToUniversalTime() - lastBootUp.ToUniversalTime();
}

Simple, no but it can be done:
static DateTime getLastBootTime(ManagementObject mObject)
{
PropertyData pd = mObject.Properties["LastBootUpTime"];
string name = pd.Name.ToString();
DateTime lastBoot = parseCmiDateTime(pd.Value.ToString());
return lastBoot;
}
static ManagementObject getServerOSObject(string serverName)
{
ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("Select * From Win32_OperatingSystem");
mSearcher.Scope = new ManagementScope(String.Format(#"\\{0}\root\cimv2", serverName));
ManagementObjectCollection mObjects = mSearcher.Get();
if (mObjects.Count != 1) throw new Exception(String.Format("Expected 1 object, returned {0}.", mObjects.Count));
foreach (ManagementObject m in mObjects)
{
//No indexing on collection
return m;
}
throw new Exception("Something went wrong!");
}

I know question is both old and solved, but the esiest solution I can tink of is just using the Enviroment.TickCount property, which returns the number of millisecounds since the system started:
System.DateTime SystemStartTime = DateAndTime.Now.AddMilliseconds(-Environment.TickCount);
System.DateTime Uptime = DateAndTime.Now - SystemStartTime;
This solition is a lot faster than the accepted answare.

The (one and only) correct answer so far:
Using the 32-bit timer is incredibly dangerous, and prone to error for all but limited use.
I'm not sure when the NativeMethods class stuff was added to .net, but it was. You definitely want to avoid P/Invoke overhead. Do this:
using System;
using System.Runtime.InteropServices;
namespace Mu
{
// prevents PInvoke (not in NativeMethods class) or Stack walk (NativeMethods class) performance penalties.
internal static partial class SafeNativeMethods
{
[DllImport("kernel32")]
internal extern static UInt64 GetTickCount64();
}
public static class MuTime
{
public static UInt64 UpTimeMillis { get { return SafeNativeMethods.GetTickCount64(); } }
}
}
/*
Dual License (use either, not both). To avoid CC-BY-SA, access a copy of this
code at (https://pastebin.com/6EKTWsSf) to use under BSD 0-clause license,
Copyright (c) 2020 Robin Davies
CC-BY-SA 3.0 (due to StackExchange terms of use). Not my fault, blame StackExchange. Fix this
please, StackExchange!
BSD 0-Clause
Copyright 2020 Robin Davies.
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
*/

Related

C# - Total Seconds expended since beginning of app use - data type [duplicate]

I am porting an app from ActionScript3.0 (Flex) to C# (WPF).AS3.0 has got a handy utility called getTimer() which returns time since Flash Virtual machine start in milliseconds.I was searching in C# through classes as
DateTime
DispatcherTimer
System.Diagnostics.Process
System.Diagnostics.Stopwatch
but found nothing like this.It seems a very basic feature to me.For example Unity3D which runs on Mono has something familiar. Do I miss some utility here?
Thanks in advance.
Process.GetCurrentProcess().StartTime is your friend.
..so to get elapsed time since start:
DateTime.UtcNow - Process.GetCurrentProcess().StartTime.ToUniversalTime()
alternatively, if you need more definition, System.Diagnostics.Stopwatch might be preferable. If so, start a stopwatch when your app starts:
Stopwatch sw = Stopwatch.StartNew();
then query the sw.Elapsed property during your execution run.
public static class Runtime
{
static Runtime()
{
var ThisProcess = System.Diagnostics.Process.GetCurrentProcess(); LastSystemTime = (long)(System.DateTime.Now - ThisProcess.StartTime).TotalMilliseconds; ThisProcess.Dispose();
StopWatch = new System.Diagnostics.Stopwatch(); StopWatch.Start();
}
private static long LastSystemTime;
private static System.Diagnostics.Stopwatch StopWatch;
//Public.
public static long CurrentRuntime { get { return StopWatch.ElapsedMilliseconds + LastSystemTime; } }
}
Then call: Runtime.CurrentRuntime to get the current programs runtime in miliseconds.
Note: You can replace the TotalMilliseconds/ElapsedMilliseconds to any other time metric you need.

C# are field reads guaranteed to be reliable (fresh) when using multithreading?

Background
My colleague thinks reads in multithreaded C# are reliable and will always give you the current, fresh value of a field, but I've always used locks because I was sure I'd experienced problems otherwise.
I spent some time googling and reading articles, but I mustn't be able to provide google with correct search input, because I didn't find exactly what I was after.
So I wrote the below program without locks in an attempt to prove why that's bad.
Question
I'm assuming the below is a valid test, then the results show that the reads aren't reliable/fresh.
Can someone explain what this is caused by? (reordering, staleness or something else)?
And link me to official Microsoft documentation/section explaining why this happens and what is the recommended solution?
If the below isn't a valid test, what would be?
Program
If there are two threads, one calls SetA and the other calls SetB, if the reads are unreliable without locks, then intermittently Foo's field "c" will be false.
using System;
using System.Threading.Tasks;
namespace SetASetBTestAB
{
class Program
{
class Foo
{
public bool a;
public bool b;
public bool c;
public void SetA()
{
a = true;
TestAB();
}
public void SetB()
{
b = true;
TestAB();
}
public void TestAB()
{
if (a && b)
{
c = true;
}
}
}
static void Main(string[] args)
{
int timesCWasFalse = 0;
for (int i = 0; i < 100000; i++)
{
var f = new Foo();
var t1 = Task.Run(() => f.SetA());
var t2 = Task.Run(() => f.SetB());
Task.WaitAll(t1, t2);
if (!f.c)
{
timesCWasFalse++;
}
}
Console.WriteLine($"timesCWasFalse: {timesCWasFalse}");
Console.WriteLine("Finished. Press Enter to exit");
Console.ReadLine();
}
}
}
Output
Release mode. Intel Core i7 6700HQ:
Run 1: timesCWasFalse: 8
Run 2: timesCWasFalse: 10
Of course it is not fresh. The average CPU nowadays has 3 layers of Caches between each cores Registers and the RAM. And it can take quite some time for a write to one cache to be propagate to all of them.
And then there is the JiT Compiler. Part of it's job is dead code dection. And one of the first things it will do is cut out "useless" variables. For example this code tried to force a OOM excpetion by running into the 2 GiB Limit on x32 Systems:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OOM_32_forced
{
class Program
{
static void Main(string[] args)
{
//each short is 2 byte big, Int32.MaxValue is 2^31.
//So this will require a bit above 2^32 byte, or 2 GiB
short[] Array = new short[Int32.MaxValue];
/*need to actually access that array
Otherwise JIT compiler and optimisations will just skip
the array definition and creation */
foreach (short value in Array)
Console.WriteLine(value);
}
}
}
The thing is that if you cut out the output stuff, there is a decent chance that the JiT will remove the variable Array inlcuding the instantionation order. The JiT has a decent chance to reduce this programming to doing nothing at all at runtime.
volatile is first preventing the JiT from doing any optimisations on that value. And it might even have some effect on how the CPU processes stuff.

My static method seems to perform faster with reuse. Why? Does it become cached?

I created code to see how fast my static compression method takes to execute, and I noticed that the first execution takes 8,500,000 nanoseconds, the second about half that, and then everything after that executes at 0 nanoseconds. Why?
private void CheckPerformance()
{
while (KeepRunning)
{
//generates a complex random 500 character string
string text = GenerateString(500, 4);
DateTime beginTime = DateTime.Now;
byte[] bytes = Compress(text); // < - timing this
long elapsedTicks = DateTime.Now.Ticks - beginTime.Ticks;
Console.WriteLine(" {0:N0} nanoseconds", elapsedTicks * 100);
//sleep for 5 seconds
Thread.Sleep(5000);
}
}
public static byte[] Compress(string text)
{
using (MemoryStream output = new MemoryStream())
{
using (DeflateStream ds = new DeflateStream(output, CompressionMode.Compress))
{
using (StreamWriter writer = new StreamWriter(ds, Encoding.UTF8))
{
writer.Write(text);
}
}
return output.ToArray();
}
}
The DateTime.Now gets updates around 10 times per second but don't quote me on this (could be depending on hardware and software setting). It's also slow because it needs to figure out what timezone the system is on. UtcNow is faster but will still be cached for a bit. Therefore, it could be using the cached version on subsequent calls.
Use StopWatch instead for more accurate measurement. StopWatch uses high precision by utilizing hardware. You can check that using Stopwatch.IsHighResolution.
using System.Diagnostics;
Stopwatch sw = new Stopwatch();
sw.Start();
// code to benchmark
sw.Stop();
Let's see if you get same metrics.
EDIT
While it is true that your method needs to be JIT compiled, the difference cannot be due to JIT compilation because it will be JIT compiled only once (not always but in your case it will be once) and then reused. Therefore, only the first call should take longer and the subsequent calls should be the same. To throw this assumption away, simply call Compress once outside the benchmarking phase so it is JIT compiled. Then benchmark it, and now the JIT compilation will not occur, and DateTime will still give you random results because it is cached.
Note: The JIT compiler does not necessarily always compile the whole method into machine code but only when execution passes through the code. So if you have if statements, the blocks may not be compiled until execution is passed through the block. But yours have no if statements so that is why it will be JIT compiled once.
Furthermore, we cannot say with confidence this was due to JIT compilation since it is possible Compress method could have been inlined but in your case it was most likely not inlined since you most likely had the debugger on and therefore, JIT optimization will be disabled.
Try this code and you will notice it gives random results for elapsed time even though the same code is executed:
for (int i = 0; i < 1000; i++)
{
DateTime beginTime = DateTime.UtcNow;
var sw = Stopwatch.StartNew();
while (sw.ElapsedTicks < 100)
{
Console.WriteLine("*");
}
long elapsedTicks = DateTime.UtcNow.Ticks - beginTime.Ticks;
Console.WriteLine(" {0:N0} nanoseconds", elapsedTicks * 100);
}
On my system if I change this line to sw.ElapsedTicks < 2050, then there is always is a difference of non zero reported consistently. Which means right around there is when DateTime.Now gets a new value instead of using the cached one.
In conclusion, I do not buy that JIT compilation is the explanation for what you are noticing.
When you hit it the first time, it gets jitted. So that takes time. Not sure though why the second and third times differ.

System Uptime & MemoryBarrier

I need a robust way of getting system uptime, and ended up using something as follows.
Added some comments to help people read it. I cannot use Task's as this has to run on a .NET 3.5 application.
// This is a structure, can't be marked as volatile
// need to implement MemoryBarrier manually as appropriate
private static TimeSpan _uptime;
private static TimeSpan GetUptime()
{
// Try and set the Uptime using per counters
var uptimeThread = new Thread(GetPerformanceCounterUptime);
uptimeThread.Start();
// If our thread hasn't finished in 5 seconds, perf counters are broken
if (!uptimeThread.Join(5 * 1000))
{
// Kill the thread and use Environment.TickCount
uptimeThread.Abort();
_uptime = TimeSpan.FromMilliseconds(
Environment.TickCount & Int32.MaxValue);
}
Thread.MemoryBarrier();
return _uptime;
}
// This sets the System uptime using the perf counters
// this gives the best result but on a system with corrupt perf counters
// it can freeze
private static void GetPerformanceCounterUptime()
{
using (var uptime = new PerformanceCounter("System", "System Up Time"))
{
uptime.NextValue();
_uptime = TimeSpan.FromSeconds(uptime.NextValue());
}
}
The part I am struggling with is where should Thread.MemoryBarrier() be placed?
I am placing it before reading the value, but either the current thread or a different thread could have written to it. Does the above look correct?
Edit, Answer based on Daniel
This is what I eneded up implementing, thank you both for the insight.
private static TimeSpan _uptime;
private static TimeSpan GetUptime()
{
var uptimeThread = new Thread(GetPerformanceCounterUptime);
uptimeThread.Start();
if (uptimeThread.Join(5*1000))
{
return _uptime;
}
else
{
uptimeThread.Abort();
return TimeSpan.FromMilliseconds(
Environment.TickCount & Int32.MaxValue);
}
}
private static void GetPerformanceCounterUptime()
{
using (var uptime = new PerformanceCounter("System", "System Up Time"))
{
uptime.NextValue();
_uptime = TimeSpan.FromSeconds(uptime.NextValue());
}
}
Edit 2
Updated based on Bob's comments.
private static DateTimeOffset _uptime;
private static DateTimeOffset GetUptime()
{
var uptimeThread = new Thread(GetPerformanceCounterUptime);
uptimeThread.Start();
if (uptimeThread.Join(5*1000))
{
return _uptime;
}
else
{
uptimeThread.Abort();
return DateTimeOffset.Now.Subtract(TimeSpan.FromMilliseconds(
Environment.TickCount & Int32.MaxValue));
}
}
private static void GetPerformanceCounterUptime()
{
if (_uptime != default(DateTimeOffset))
{
return;
}
using (var uptime = new PerformanceCounter("System", "System Up Time"))
{
uptime.NextValue();
_uptime = DateTimeOffset.Now.Subtract(
TimeSpan.FromSeconds(uptime.NextValue()));
}
}
Thread.Join already ensures that writes performed by the uptimeThread are visible on the main thread. You don't need any explicit memory barrier. (without the synchronization performed by Join, you'd need barriers on both threads - after the write and before the read)
However, there's a potential problem with your code: writing to a TimeSpan struct isn't atomic, and the main thread and the uptimeThread may write to it at the same time (Thread.Abort just signals abortion, but doesn't wait for the thread to finish aborting), causing a torn write.
My solution would be to not use the field at all when aborting. Also, multiple concurrent calls to GetUptime() may cause the same problem, so you should use an instance field instead.
private static TimeSpan GetUptime()
{
// Try and set the Uptime using per counters
var helper = new Helper();
var uptimeThread = new Thread(helper.GetPerformanceCounterUptime);
uptimeThread.Start();
// If our thread hasn't finished in 5 seconds, perf counters are broken
if (uptimeThread.Join(5 * 1000))
{
return helper._uptime;
} else {
// Kill the thread and use Environment.TickCount
uptimeThread.Abort();
return TimeSpan.FromMilliseconds(
Environment.TickCount & Int32.MaxValue);
}
}
class Helper
{
internal TimeSpan _uptime;
// This sets the System uptime using the perf counters
// this gives the best result but on a system with corrupt perf counters
// it can freeze
internal void GetPerformanceCounterUptime()
{
using (var uptime = new PerformanceCounter("System", "System Up Time"))
{
uptime.NextValue();
_uptime = TimeSpan.FromSeconds(uptime.NextValue());
}
}
}
However, I'm not sure if aborting the performance counter thread will work correctly at all - Thread.Abort() only aborts managed code execution. If the code is hanging within a Windows API call, the thread will keep running.
AFAIK writes in .NET are volatile, so the only place where you would need a memory fence would be before each read, since they are subject to reordering and/or caching. To quote from a post by Joe Duffy:
For reference, here are the rules as I have come to understand them
stated as simply as I can:
Rule 1: Data dependence among loads and stores is never violated.
Rule 2: All stores have release semantics, i.e. no load or store may move after one.
Rule 3: All volatile loads are acquire, i.e. no load or store may move before one.
Rule 4: No loads and stores may ever cross a full-barrier.
Rule 5: Loads and stores to the heap may never be introduced.
Rule 6: Loads and stores may only be deleted when coalescing adjacent loads and
stores from/to the same location.
Note that by this definition, non-volatile loads are not required to
have any sort of barrier associated with them. So loads may be freely
reordered, and writes may move after them (though not before, due to
Rule 2). With this model, the only true case where you’d truly need
the strength of a full-barrier provided by Rule 4 is to prevent
reordering in the case where a store is followed by a volatile load.
Without the barrier, the instructions may reorder.

Measure execution time in C#

I want to measure the execution of a piece of code and I'm wondering what the best method to do this is?
Option 1:
DateTime StartTime = DateTime.Now;
//Code
TimeSpan ts = DateTime.Now.Subtract(StartTime);
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine(elapsedTime, "RunTime");
Option 2:
using System.Diagnostics;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
//Code
stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;
// Format and display the TimeSpan value.
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine(elapsedTime, "RunTime");
This isn't simply for benchmarking, its actually part of the application. The time the function takes to execute is relevant data. It doesn't however need to be atomic or hyper-accurate.
Which option is better for production code, or does anybody else use something different and perhaps better?
The Stopwatch class is specifically designed to measure elapsed time and may (if available on your hardware) provide good granularity/accuracy using an underlying high-frequency hardware timer. So this seem the best choice.
The IsHighResolution property can be used to determine whether high resolution timing is available. Per the documentation, this class offers a wrapper on the 'best available' Win32 APIs for accurate timing:
Specifically, the Frequency field and
GetTimestamp method can be used in
place of the unmanaged Win32 APIs
QueryPerformanceFrequency and
QueryPerformanceCounter.
There is detailed background on those Win32 APIs [here] and in linked MSDN docs 2.
High-Resolution Timer
A counter is a general term used in
programming to refer to an
incrementing variable. Some systems
include a high-resolution performance
counter that provides high-resolution
elapsed times.
If a high-resolution performance
counter exists on the system, you can
use the QueryPerformanceFrequency
function to express the frequency, in
counts per second. The value of the
count is processor dependent. On some
processors, for example, the count
might be the cycle rate of the
processor clock.
The QueryPerformanceCounter function
retrieves the current value of the
high-resolution performance counter.
By calling this function at the
beginning and end of a section of
code, an application essentially uses
the counter as a high-resolution
timer. For example, suppose that
QueryPerformanceFrequency indicates
that the frequency of the
high-resolution performance counter is
50,000 counts per second. If the
application calls
QueryPerformanceCounter immediately
before and immediately after the
section of code to be timed, the
counter values might be 1500 counts
and 3500 counts, respectively. These
values would indicate that .04 seconds
(2000 counts) elapsed while the code
executed.
It's not just that StopWatch is more accurate, but also that DateTime.Now will give incorrect results in some circumstances.
Consider what happens during a daylight saving time switch-over, for example — using DateTime.Now can actually give a negative answer!
I generally use StopWatch for this kind of situation.
From MSDN page:
StopWatch
Provides a set of methods and
properties that you can use to
accurately measure elapsed time.
In the following post I use it to compare the execution time of LINQ vs PLINQ:
Parallel LINQ (PLINQ) with Visual Studio 2010
Neither will hurt the performance, because you say it is not that critical. StopWatch seems more appropriate - you are only subtracting time from time and not one date from another. Date stuff takes a tad more memory and CPU time to deal with. There are also ways to make the code cleaner, in case you plan on reusing it in several places. Overloading using comes to mind. I will search for an example. Ok, code stolen from:
http://stevesmithblog.com/blog/great-uses-of-using-statement-in-c/
public class ConsoleAutoStopWatch : IDisposable
{
private readonly Stopwatch _stopWatch;
public ConsoleAutoStopWatch()
{
_stopWatch = new Stopwatch();
_stopWatch.Start();
}
public void Dispose()
{
_stopWatch.Stop();
TimeSpan ts = _stopWatch.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine(elapsedTime, "RunTime");
}
}
private static void UsingStopWatchUsage()
{
Console.WriteLine("ConsoleAutoStopWatch Used: ");
using (new ConsoleAutoStopWatch())
{
Thread.Sleep(3000);
}
}
Both will likely fit your needs just fine, but I would say use StopWatch. Why? Cause it's meant for the task you're doing.
You've got one class that's built to return the current date/time, which as it happens can be used for timing things, and you've got one class specifically designed for timing things.
In this case the differences only really exist if you need millisecond accuracy (In which case StopWatch is more accurate), but as a general principal if a tool exists specifically for the task you're looking for then it's the better one to use.
I have a little class to do this sort of thing ad hoc. It uses the stopwatch class - c# micro perfomance testing.
eg.
var tester = new PerformanceTester(() => SomeMethod());
tester.MeasureExecTime(1000);
Console.Writeline(string.Format("Executed in {0} milliseconds", tester.AverageTime.TotalMilliseconds));
Use below code
DateTime dExecutionTime;
dExecutionTime = DateTime.Now;
TimeSpan span = DateTime.Now.Subtract(dExecutionTime);
lblExecutinTime.Text = "total time taken " + Math.Round(span.TotalMinutes,2) + " minutes . >>---> " + DateTime.Now.ToShortTimeString();
I took Hamish's answer simplified it and made it a bit more general in case you need to log to somewhere else:
public class AutoStopWatch : Stopwatch, IDisposable {
public AutoStopWatch() {
Start();
}
public virtual void Dispose() {
Stop();
}
}
public class AutoStopWatchConsole : AutoStopWatch {
private readonly string prefix;
public AutoStopWatchConsole(string prefix = "") {
this.prefix = prefix;
}
public override void Dispose() {
base.Dispose();
string format = Elapsed.Days > 0 ? "{0} days " : "";
format += "{1:00}:{2:00}:{3:00}.{4:00}";
Console.WriteLine(prefix + " " + format.Format(Elapsed.Days, Elapsed.Hours, Elapsed.Minutes, Elapsed.Seconds, Elapsed.Milliseconds / 10));
}
}
private static void Usage() {
Console.WriteLine("AutoStopWatch Used: ");
using (var sw = new AutoStopWatch()) {
Thread.Sleep(3000);
Console.WriteLine(sw.Elapsed.ToString("h'h 'm'm 's's'"));
}
Console.WriteLine("AutoStopWatchConsole Used: ");
using (var sw = new AutoStopWatchConsole()) {
Thread.Sleep(3000);
}
}

Categories