Stopwatch Time Elapsed Zero - c#

I have two actions in mvc and in one I start a global stopwatch and in another I stop it, but the time elapsed is always 0 no matter how long the time elapsed is. Both of these events are triggered by button clicks. My suspition is that the post of the button is messing with my time elapsed maybe? If so is there any way around this?
public Stopwatch stopwatch = new Stopwatch();
public ActionResult Start()
{
stopwatch.Start();
return RedirectToAction("Index");
}
public ActionResult Stop(int workid)
{
stopwatch.Stop();
TimeSpan ts = stopwatch.Elapsed;
int hours = ts.Hours;
int mins = ts.Minutes;
using (ZDevContext db = new ZDevContext())
{
DashboardHelper dashhelper = new DashboardHelper(db);
dashhelper.RecordTimeSpent(workid, hours, mins);
}
return View("Index");
}

It's not the same StopWatch - the controller is created anew for each request. You would need to persist the stopwatch somewhere.
You could persist the start time in a static Dictionary<int,DateTimeOffset> which would map a workId to the started time.
static ConcurrentDictionary<int,DateTimeOffset> starts = new ConcurrentDictionary<int,DateTimeOffset>();
public ActionResult Start(int workId)
{
starts.TryAdd(workId, DateTimeOffset.Now);
return RedirectToAction("Index");
}
public ActionResult Stop(int workId)
{
DateTimeOffset started = DateTimeOffset.MinValue;
if (starts.TryGet(workId, out started))
{
// calculate time difference
}
return View("Index");
}
But this still isn't great as your application may be restarted by IIS in between and you will lose the starts value. It also has no code to clean the table when a value is no longer needed. You could improve the latter by using the .NET Cache but you really need a database to do this right.

if you want to make the same instance shared for all sessions (which you usually don't want) just mark it as static,
private static Stopwatch stopwatch = new Stopwatch();
also, you don't have to define it as public if it will not be accessible from other controllers/assemblies.
as #Ian Mercer suggested, it is not a good way to use for a stopwatch.
have a look at these links:
Access modifiers
static c#

Related

Time measurement of functions with different signature in C#

I want to measure the time that certain function calls take in my application. For this I use the Stopwatch class and it works fine. It looks something like this:
static readonly Stopwatch StopWatch = new Stopwatch();
StopWatch.Restart();
void func();
StopWatch.Stop();
Assert.Blabla
However I am typing this around a lot of functions. Is there a way to make a function that does this for me? I tried but since the signatures of the functions are all different I can't figure it out. I took a look at Func and Action, but they seem to require a fixed signature. I would like something like this:
CallAndMeasureFunction(func)
You can use something like below:
Define a method which takes your actual methods delegate as input:
public static TimeSpan GetTimestampFor(Action action)
{
TimeSpan timestamp = new TimeSpan(0);
Stopwatch stopWatch = new Stopwatch();
if (action != null)
{
stopWatch.Start();
action.Invoke();
stopWatch.Stop();
timestamp = stopWatch.Elapsed;
}
return timestamp;
}
and call it as below:
var timeSpan = GetTimestampFor(() => {var xyz = ActualMethodForWhichTimeHasTobeMeasured()});
With this code, you can measure every method's execution time

Get time process takes to complete in seconds?

My program runs a batch file in cmd.exe, after it finished I want to display a MessageBox to user saying Finished in #.## seconds,
I'm redirecting CMD output to a textbox using process.BeginOutputReadLine(), this is the code I tried:
if (e.Data == null)
{
string time = process.TotalProcessorTime.Seconds.ToString();
MessageBox.Show("Finished in " + time + " seconds");
}
It took about 7-15 seconds to complete the process, but the MessageBox displayed Finished in 0 seconds.
How do I get the accurate time it took to complete in seconds?
Stopwatch watch = new Stopwatch();
watch.Start();
//Do things
watch.Stop();
Text = watch.Elapsed.TotalSeconds.ToString();
Have you tried process.ExitTime.Subtract(process.StartTime).TotalSeconds?
Edited to add: Note that you will get an exception if you try to use this before the process has exited. Per the documentation for ExitTime, use the HasExited property if you have any doubt as to whether this is the case or not.
Could you ultimately do something like this if it makes it easier to read for you
var procTime = DateTime.Now - Process.GetCurrentProcess().StartTime;
var procTimeInSec = procTime.Seconds;
MessageBox.Show(string.Format("Finished in {0} seconds", procTimeInSec));
to access you may want to change the two `var local variables to be accessible from outside the local scope.
below is how you would declare it outside of the local method at the top of the Class
public static TimeSpan procTime = new TimeSpan();
var procTimeInSec, can still be declared in the local scope
Just basic Stopwatch should be enough.
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
// run external process, if asynchronous -
//store stopWatch in member variable instead of local
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Note that TotalProcessorTime measures CPU usage time, which could very well be 0 seconds for CMD.exe as it really does not do much.
You should look into the Stopwatch class. You'll need to start the stopwatch before your process begins, then stop it afterwards and get the elapsed time.
You should use the Stopwatch class when starting the process.
On the process, add an event handler for the Exited event and when the process is done, stop the stopwatch and retrieve the time.
class Foo
{
Stopwatch watch = new Stopwatch();
public void RunProcess(Process process)
{
process.Exited += new EventHandler(ProcessExit);
process.Start();
watch.Start();
}
public void ProcessExit(object sender, EventArgs e)
{
watch.Stop();
}
}

Measuring the execution time in multithreading environment

I have an application that uses Task (TPL) objects for asynchronous execution.
The main thread waits for a trigger (some TCP packet) and then executes several tasks. What I want to do is to measure the time spent in the tasks.
Take a look at the code. I have some lengthy operation (Generator), enclosed in Stopwatch's start/stop.
Task.Factory.StartNew((t) => {
Stopwatch sw = new Stopwatch();
sw.Start();
Generator g = new Generator();
g.GenerateIntervals(); // lengthy operation
sw.Stop();
GlobalStopwatch.Add(sw.Elapsed);
});
Here is the problem. Stopwatch uses DateTime.UtcNow.Ticks at the moment of Start() and then again at the moment of Stop(). Then it subtracts those two to get the elapsed time.
The thing is, some other thread (in a single-threaded system) can get some processor time while the Generator (from the code) is doing its GenerateIntervals() lengthy operation. That means that the elapsed time recorded by the stopwatch would contain not only the Generaor.GenerateIntervals() time, but also the time that the other threads did their job inbetween.
Is there any simple way to know exactly how much of processor time did some method take, not including execution time from other threads as a result of timesharing mechanisms?
The answer to your question is "No"... No, you cannot measure the accumulated time ON THE CPU for a particular thread.
(Side-rant: I really wish people would read the question and understand it before answering!!!)
Ok, back to your question... the most accurate thing you could do would be to spin off a separate process for each of your tasks, and then measure the CPU time for the process (which can be done in .Net)... but that's overkill.
If you need help on how to do that, you should ask another question specifically for that.
Here is nice Article . You can use it or you can compare those times using in-built performance analyzer in VS2010.
You could use the Windows API QueryPerformanceCounter() and QueryPerformanceFrequency() methodsto retrieves the number of milliseconds that have elapsed since the timer was started.
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Threading;
namespace Win32
{
internal class WinTimer
{
[DllImport("Kernel32.dll")]
private static extern bool QueryPerformanceCounter(
out long lpPerformanceCount);
[DllImport("Kernel32.dll")]
private static extern bool QueryPerformanceFrequency(
out long lpFrequency);
private long startTime, stopTime;
private long freq;
// Constructor
public HiPerfTimer()
{
startTime = 0;
stopTime = 0;
if (QueryPerformanceFrequency(out freq) == false)
{
// high-performance counter not supported
throw new Win32Exception();
}
}
// Start the timer
public void Start()
{
// lets do the waiting threads there work
Thread.Sleep(0);
QueryPerformanceCounter(out startTime);
}
// Stop the timer
public void Stop()
{
QueryPerformanceCounter(out stopTime);
}
// Returns the duration of the timer (in seconds)
public double Duration
{
get
{
return (double)(stopTime - startTime) / (double) freq;
}
}
}
}
In fact the answer is YES (but you need to use interop).
There is a WINAPI function which is called QueryThreadCycleTime and does exactly this:
"Retrieves the cycle time for the specified thread."

Create timer and start it and get its value at anytime c#

I want to create a timer and start it and gets its value at any time in C# and I want to know what it is, depending on, for example, is it by seconds or milliseconds or so forth.
Are you looking for the Stopwatch class?
using System.Diagnostics;
// ...
var stopwatch = Stopwatch.StartNew();
// ...
var milliseconds = stopwatch.ElapsedMilliseconds;
Have you looked at Stopwatch class?
http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx
This is another link with some good examples:
http://www.dotnetperls.com/stopwatch
var start = Environment.TickCount;
// loop for 2 seconds
while(Environment.TickCount-start <2000)
{
Console.Write(".");
}
Console.WriteLine("done");

How make time elapsed method?

I need a method that give me the time elapsed awhile my process. I call it at start the process and call it again at finish the process, and the method print the total time elapsed.
This is my method, but always print the time in 00:00. Why is happening this??
public void GetTimeElapsed(string filePath, int logSelected, bool time, IUserOptions userOptions)
{
var stopwatch = new System.Diagnostics.Stopwatch();
LogBinaryWriter BinaryWriter = new LogBinaryWriter();
string timeElapsed = "";
if(time == true)
{
stopwatch.Start();
}
if (time == false)
{
stopwatch.Stop();
TimeSpan timeSpan = stopwatch.Elapsed;
timeElapsed = (string.Format("\nFile Generated: {0}\nTime Elapsed: {1} minute(s) {2} second(s)",
BinaryWriter.CreateLogFileName(filePath, Convert.ToInt32(logSelected)),
timeSpan.Minutes, timeSpan.Seconds, timeSpan.Milliseconds / 10 + "\n"));
userOptions.DisplayUserMessage(timeElapsed);
}
}
Look where you're declaring stopwatch; it's a local variable. That means you're creating and using two different stopwatches; the first one is started when you call the method with a "true" parameter, then disposed of when the method ends and the variable goes out of scope. The second is declared, never started, then its time examined and logged.
To solve the problem, declare an instance variable ("field") for the Stopwatch. That will keep it in scope as long as the object is around, meaning it will keep running after the method ends, and will still be the same instance when you come back to it to stop and examine it.
Your stopwatch variable is local. When you call the function a second time, it's initialized again.
You need to move the declaration up to class level.
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
public void GetTimeElapsed(string filePath, int logSelected, bool time, IUserOptions userOptions)
{
... etc
You're creating a new stopwatch each time this method is called, but it looks like that should be persistent between method calls.
Take the stopwatch variable declaration outside of the method.
What about using:
var startTime = DateTime.Now;
... your code
var elapsed = DateTime.Now - startTime;
if(time == true)
{
stopwatch.Start();
}
if (time == false)
{
stopwatch.Stop();
...
}
If time is true, you only ever start the stopwatch.
If it is false, you never start it.
A better structure would be:
if(time)
{
stopwatch.Start();
}
... //code to measure here
if (time)
{
stopwatch.Stop();
// log elapsed time
}
Note:
If you have a boolean type, you don't compare it to true or false. Just use it directly and if you want to invert it just use !.
You need to use timeSpan.TotalMinutes instead timestamp.Minutes. Refer timespan documentation

Categories

Resources