I have this code:
public void replay() {
long previous = DateTime.Now.Ticks;
for (int i = 0; i < 1000; i++) {
Thread.Sleep(300);
long cur = DateTime.Now.Ticks;
Console.WriteLine(cur - previous);
previous = cur;
}
}
Which is invoked as a separate thread like this:
MethodInvoker replayer = new MethodInvoker(replay);
replayer.BeginInvoke(null, null);
However, if I watch the output, it acts strangely. It outputs i in pairs. For example, it'll wait a full wait, then output i, then quickly output the next i too, then wait again. Why is it doing that and how can I correct it?
It outputs this:
3125040
2968788
2968788
2968788
3125040
2968788
2968788
2968788
3125040
2968788
2968788
2968788
3125040
If I increase the sleep to more than a second this doesn't happen.
Change the code to eliminate display latency in your analysis:
public void replay()
{
Thread.Sleep(5000);
DateTime start = DateTime.Now;
for (int i = 0; i < 1000; i++)
{
Console.WriteLine(string.Format("Exec:{0} - {1} ms",
i, DateTime.Now - start));
start = DateTime.Now;
Thread.Sleep(300);
}
}
Looking at your modified output, there is less than 5% variance (15ms out of the 300) in the loop delay. This is normal, due to the uncertainties involved in when the OS actually assigns timeslices to the thread... (If I recall correctly, in a windows OS, this is normally only every 20 ms !)
The larger discrepancy you perceive in the console output is almost certainly due to display latencys.
Cannot reproduce. I wonder if it is something local to your machine; buffering, perhaps.
I can't reproduce this, but you might want to consider a timer. It would be more reliable.
public class Counter
{
private readonly TimeSpan initialDelay, incrementDelay;
private readonly int maxCount;
private Timer timer;
private int count;
public Counter(TimeSpan initialDelay, TimeSpan incrementDelay, int maxCount)
{
this.maxCount = maxCount;
this.initialDelay = initialDelay;
this.incrementDelay = incrementDelay;
}
public void Start(Action<int> tickBehavior)
{
if (timer != null)
{
Timer temp = timer;
timer = null;
temp.Dispose();
}
timer = new Timer(() =>
{
tickBehavior(count++);
if (count > maxCount) timer.Dispose();
}, null, initialDelay, incrementDelay);
}
}
Use it:
Counter counter = new Counter(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(.3), 1000);
counter.Start((count) => Console.WriteLine(count););
EDIT
I'm using System.Threading.Timer, but Counter could be easily be modified to use System.Timers.Timer or System.Windows.Forms.Timer depending on your need. See this link for a description of when to use which timers.
Your sleep inside the loop is only 300ms, which isn't very long. You application will do the following:
Sleep 5 secs
print 0
Sleep 300ms
print 1
Sleep 300ms
print 2
etc.
Related
I am trying to refresh my frame every 17ms with a timer.
Timer timer = new Timer(17);
timer.Elapsed += ResetFrame;
timer.Start();
But instead of waiting for 17ms and then repeating, it waited for the frame refresh to complete and then wait for 17msfor the next repeat. This causes the frame to be refreshed every 28ms. How to synchronize it with real time?
To have a real time timer having a very short interval, you can take a look at this article:
Real Time Timer in C#
In Dot Net, following timers are not real time.
System.Windows.Forms.Timer
System.Timers.Timer
System.Threading.Timer
Means if you want to run your code at every 100 millisecond then above
timer fire even around 110 millisecond or later. Windows is not a real
time OS because of this .Net is also not a real time.
To create a real time timer in C# you have to write custom code that
can hold CPU to run your code at right time.
class Program
{
static void Main(string[] args)
{
Console.ReadLine();
Console.WriteLine("Running");
RealTimeTimerTest obj = new RealTimeTimerTest();
obj.Run();
}
}
public class RealTimeTimerTest
{
List<DateTime> lst = new List<DateTime>();
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
public void Run()
{
int Tick = 100;
int Sleep = Tick - 20;
long OldElapsedMilliseconds = 0;
sw.Start();
while (sw.IsRunning)
{
long ElapsedMilliseconds = sw.ElapsedMilliseconds;
long mod = (ElapsedMilliseconds % Tick);
if (OldElapsedMilliseconds != ElapsedMilliseconds && (mod == 0 || ElapsedMilliseconds > Tick))
{
//-----------------Do here whatever you want to do--------------Start
lst.Add(DateTime.Now);
//-----------------Do here whatever you want to do--------------End
//-----------------Restart----------------Start
OldElapsedMilliseconds = ElapsedMilliseconds;
OldElapsedMilliseconds = 0;
sw.Reset();
sw.Start();
System.Threading.Thread.Sleep(Sleep);
//-----------------Restart----------------End
}
//------------Must define some condition to break the loop here-----------Start
if (lst.Count > 500)
{
Write();
break;
}
//-------------Must define some condition to break the loop here-----------End
}
}
private void Write()
{
System.IO.StreamWriter sw = new System.IO.StreamWriter("d:\\text.txt", true);
foreach (DateTime dtStart in lst)
sw.WriteLine(dtStart.ToString("HH:mm:ss.ffffff")); sw.Close();
}
}
Also that:
Most accurate timer in .NET?
High resolution timer
High resolution timer in C#
Microsecond and Millisecond C# Timer
Precision-Repeat-Action-On-Interval-Async-Method
I'm writing an app where a user specifies a length of time, length of an interval and a length of time in between intervals. I want to have a timer label showing the user the total time but then I also want to have a label showing the work status (recording if in the interval, break if between interval time and break end).
Heres an Example: Total time = 2 min, Interval = 20 seconds, Break = 10 seconds
In this example there will be 4 intervals. So from 0:00-0:19 I want to display "Recording" and then from 0:20-0:29 I want to display break and then from 0:30-0:49 I display "Recording" and 0:50-0:59 I display "Break" and so on. All while the timer counts the time.
So I thought this would be pretty straightforward but what seems to happen is the timer increments properly but after the 1st interval the label doesnt switch from break to recording until 0:31 or 0:32 so it looks a little delayed.
Here is the code I am using currently (Note obs is an object Im passing in that has data from user input).
int TotalInterval = obs.Interval + obs.Break;
int WorkingInterval = obs.Interval;
int NumberOfIntervals = (obs.Duration*60) / TotalInterval;
DateTime ObservationEnd = obs.DateCreated.AddMinutes(obs.Duration);
Timer.Text = "Starting Timer";
int minutes = 0;
int seconds = 0;
int InIntervalCounter = 0;
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
// called every 1 second
Timer.Text = "Started";
if (ObservationEnd < DateTime.UtcNow)
{
Timer.Text = "Time Over";
Results.IsVisible = true;
return false;
}
else
{
seconds++;
InIntervalCounter++;
if (InIntervalCounter > WorkingInterval)
IntervalOrBreak.Text = "Break";
if (InIntervalCounter > TotalInterval)
{
IntervalOrBreak.Text = "Recording";
InIntervalCounter = 0;
}
Timer.Text = "Time: " + minutes + ":" + seconds.ToString("D2");
return true;
}
});
I'm pretty new to app development/xamarin so any help is greatly appreciated.
Try using simple Threads with Thead.sleep() like this:
final long delay_millis = 100;
Thread thread_something;
thread_something = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
long start_time = SystemClock.elapsedRealtime();
// Do some task
long time_need_for_delay = (start_time + delay_millis) - SystemClock.elapsedRealtime();
if(time_need_for_delay > 0)
thread_something.sleep(time_need_for_delay);
} catch (Exception e) { }
}
}
});
thread_something.start();
after the 1st interval the label doesnt switch from break to recording
until 0:31 or 0:32 so it looks a little delayed.
If you want to display break from 0:20-0:29 and display "Recording" from 0:30-0:49, I think the if statement should change to InIntervalCounter >= WorkingInterval and InIntervalCounter >= TotalInterval, InIntervalCounter > WorkingInterval may cause the 1 second delay.
I can't get the timer to fire once a minute on the minue, 1:00, 1:01, 1:02 etc. Instead, when the timer executes drifts by a couple of seconds each iteration
internal void StartTimer()
{
DateTime nowEastern = CalendarEntity.Calendar.GetEasternTime();
int secondsInterval = 5;
double additionalSeconds = secondsInterval - nowEastern.TimeOfDay.TotalSeconds % secondsInterval;
if (additionalSeconds == 0)
{
additionalSeconds = 1;
}
var nearestOnOneMinutes = new DateTime(
nowEastern.Year,
nowEastern.Month,
nowEastern.Day,
nowEastern.Hour,
nowEastern.Minute,
nowEastern.Second
).AddSeconds(additionalSeconds);
TimeSpan timeToStart = nearestOnOneMinutes.Subtract(nowEastern);
TimeSpan tolerance = TimeSpan.FromSeconds(1);
if (timeToStart < tolerance)
{
timeToStart = TimeSpan.Zero;
}
timer_onem = new System.Threading.Timer(OnTimedEvent, null,
(int)timeToStart.TotalMilliseconds, Timeout.Infinite);
}
private static void OnTimedEvent(object o)
{
var minute = DateTime.Now.Minute;
var second = DateTime.Now.Second;
if (minute != lastMinute && second % 60 < 2)
{
lastMinute = minute;
CodeToExecute();
}
}
static void CodeToExecute()
{
double tms = 60000;
// code here
int wait = 60 - System.DateTime.Now.Second;
timer_onem.Change(Convert.ToInt64(tms) - wait, Timeout.Infinite);
}
EDIT 1
I changed the interval so that it fires once a second and then check that the minute has changed. Still drifts
timer_onem = new System.Threading.Timer(OnTimedEvent, null,
(int)timeToStart.TotalMilliseconds, 1000);
private static void OnTimedEvent(object o)
{
var minute = DateTime.Now.Minute;
if (minute != lastMinute)
{
lastMinute = minute;
CodeToExecute();
}
}
private static void CodeToExecute()
{
if (bGenerate)
{
double tms = 1000;
// code
timer_onem.Change(Convert.ToInt64(tms), 1000);
}
}
A Timer is only guaranteed to be no faster than Interval.
So you need to call it, say every second and check for the full minute.
For even better precision you would have to check every 1/2 second or better.
It is a basic rule of information theory that says that to measure with a given resolution (1 second in your case) you need to sample with better than twice that resolution. Hence to measure 20kHz you need a smpling rate better than 2x20kHz, say 44.1kHz. (Recognize the numbers?)
If you don't want to call it so often for simply getting one precise point in time, you could write a little more involved code that on each Tick resets the Timer.Interval to a little under half of the remaining time until the next full minute until it is under say 500ms..
There are rather complex things going on in your code wrt to setting up the expected time, though; do make sure they are not the real problem. There should not be a growing drift from the timer's lack of precision, unless you 'collect' the errors..
timer1= new System.Windows.Forms.Timer();
timer1.Interval =60000; // 1 min
timer1.Start();
MyMethodName();
timer1.Stop();
MyMethodName()
-has a for loop for 90,000 entries (and some validations inside that for loop).
for (int i = 0; i <= 90000; i++)
{
//validations go here
}
When the time in timer1 is done for a minute, i want to stop executing other entries in the for loop.
For example, if 45,000 entries are done in a minute, i want to stop executing the method ie. stop the method after a minute.
However the above timer code, executes till all the 90000 records are done looping inside the for loop, somehow the method doesn't run for a minute? Any help?
Two things. Firstly Your timer code is not actually connected to the running of MyMethodName. A timer is designed to run processes when the time has elapsed (and possibly at regular intervals depending on how it is set up.
Secondly and more to the point of your question to abort a loop you have to put code inside the loop. The key would be to have a stopwatch or similar start before your loop and then at the beginning of your loop check how much time has elapsed. If it is a minute or more then break;.
The key thing to note is that you will not stop exactly on a minute but you will finish the iteration of the loop that is running when the minute expires and then stop. This is usually what you want since stopping processing midway through something may cause nasty side effects.
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i =0; i<=90000; i++)
{
if (stopwatch.Elapsed>TimeSpan.FromSeconds(5))
break;
Console.WriteLine(i);
Thread.Sleep(1000);
}
Note that Thread.Sleep is there just because otherwise I get through all 90000 iterations too quickly. ;-)
So you would likely need a much different implementation. Consider this:
public class MyForm
{
private BackgroundWorker _worker;
public MyForm()
{
_worker = new BackgroundWorker();
_worker.DoWork += (s, args) =>
{
var timer = Stopwatch().StartNew();
do
{
// do something
} while (timer.ElapsedMilliseconds < 60000)
};
}
}
and then when you want to run it:
_worker.RunWorkerAsync();
However, you could make it even more robust. You could pass the time in like this:
_worker.RunWorkerAsync(60000);
and then in the DoWork handler, do this:
while (timer.ElapsedMilliseconds < (int)args.Argument)
Further, with the BackgroundWorker, you could support cancellation. Just set the WorkerSupportsCancellation flag to true and then in the condition do this:
while (timer.ElapsedMilliseconds < (int)args.Argument && !_worker.CancellationPending)
so, if necessary, you could do this:
_worker.CancelAsync();
Hmm, use a stopwatch instead
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
for(int i= 0; i <= 90000; i++)
{
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;
if(ts.Seconds >= 60)
break;
}
However the above timer code, executes till all the 90000 records are done looping inside the for loop, somehow the method doesn't run for a minute? Any help?
The timer will not raise events until you free up the UI thread, which won't occur until after the method completes fully.
If you want to prevent the method from running past a specific duration, you could handle it in your method directly:
MyMethodName(TimeSpan.FromMinutes(1));
Then, in your method:
void MyMethodName(TimeSpan maxRuntime)
{
DateTime expiration = DateTime.Now + maxRuntime;
for (int i = 0; i <= 90000; i++)
{
//validations go here
if (i % 100 == 0) // check every 100?
{
if (DateTime.Now > expiration)
break;
}
}
}
That being said, a better approach would be to push this into a background thread, and cancel as needed.
you can set a flag on in validations to see if it is done or not by hooking up an event handler to the Tick event in the Timer object
//in an area accessible to
//both elements
object readonly _lock = new object();
bool elapsed = false;
where your original code was
elapsed = false;
timer1= new System.Windows.Forms.Timer();
timer1.Interval =60000; // 1 min
timer1.Tick=((sender, everntArgs)=>
{
lock(_lock)
elapsed = true;
});
timer1.Start();
MyMethodName();
timer1.Stop();
Inside of MyMethodName
//inside the loop
for (int i = 0; i <= 90000; i++)
{
//validations go here
lock(_lock)
if(elapsed)
break;
}
If you use a CancellationTokenSource with the CancellationTokenSource(TimeSpan) constructor, it makes it easy to write a method that will cancel an action after a specified time.
You can write a method like so:
public static void RunTimedAction(Action<CancellationToken> action, TimeSpan timeout)
{
using (var cancellationTokenSource = new CancellationTokenSource(timeout))
action(cancellationTokenSource.Token);
}
And then you can write any action that takes a CancellationToken as a parameter, like this:
private void action(CancellationToken cancel)
{
int i;
for (i = 0; i < 1000000; ++i)
{
if (cancel.IsCancellationRequested)
break;
Thread.Sleep(10); // Simulate work.
}
Console.WriteLine("action() reached " + i);
}
Which you can use like this:
Console.WriteLine("Started at " + DateTime.Now);
RunTimedAction(action, TimeSpan.FromSeconds(10));
Console.WriteLine("Stopped at " + DateTime.Now);
Let's put this together into a complete demo program:
using System;
using System.Threading;
namespace Demo
{
class Program
{
void run()
{
Console.WriteLine("Started at " + DateTime.Now);
RunTimedAction(action, TimeSpan.FromSeconds(10));
Console.WriteLine("Stopped at " + DateTime.Now);
}
private void action(CancellationToken cancel)
{
int i;
for (i = 0; i < 1000000; ++i)
{
if (cancel.IsCancellationRequested)
break;
Thread.Sleep(10); // Simulate work.
}
Console.WriteLine("action() reached " + i);
}
public static void RunTimedAction(Action<CancellationToken> action, TimeSpan timeout)
{
using (var cancellationTokenSource = new CancellationTokenSource(timeout))
action(cancellationTokenSource.Token);
}
static void Main()
{
new Program().run();
}
}
}
How could I generate steady CPU load in C#, lower than 100% for a certain time? I would also like to be able to change the load amount after a certain period of time. How do you recommend to generate usage spikes for a very short time?
First off, you have to understand that CPU usage is always an average over a certain time. At any given time, the CPU is either working or it is not. The CPU is never 40% working.
We can, however, simulate a 40% load over say a second by having the CPU work for 0.4 seconds and sleep 0.6 seconds. That gives an average utilization of 40% over that second.
Cutting it down to smaller than one second, say 100 millisecond chunks should give even more stable utilization.
The following method will take an argument that is desired utilization and then utilize a single CPU/core to that degree:
public static void ConsumeCPU(int percentage)
{
if (percentage < 0 || percentage > 100)
throw new ArgumentException("percentage");
Stopwatch watch = new Stopwatch();
watch.Start();
while (true)
{
// Make the loop go on for "percentage" milliseconds then sleep the
// remaining percentage milliseconds. So 40% utilization means work 40ms and sleep 60ms
if (watch.ElapsedMilliseconds > percentage)
{
Thread.Sleep(100 - percentage);
watch.Reset();
watch.Start();
}
}
}
I'm using a stopwatch here because it is more accurate than the the TickCount property, but you could likewise use that and use subtraction to check if you've run long enough.
Two things to keep in mind:
on multi core systems, you will have to spawn one thread for each core. Otherwise, you'll see only one CPU/core being exercised giving roughly "percentage/number-of-cores" utilization.
Thread.Sleep is not very accurate. It will never guarantee times exactly to the millisecond so you will see some variations in your results
To answer your second question, about changing the utilization after a certain time, I suggest you run this method on one or more threads (depending on number of cores) and then when you want to change utilization you just stop those threads and spawn new ones with the new percentage values. That way, you don't have to implement thread communication to change percentage of a running thread.
Just in add of the Isak response, I let here a simple implementation for multicore:
public static void CPUKill(object cpuUsage)
{
Parallel.For(0, 1, new Action<int>((int i) =>
{
Stopwatch watch = new Stopwatch();
watch.Start();
while (true)
{
if (watch.ElapsedMilliseconds > (int)cpuUsage)
{
Thread.Sleep(100 - (int)cpuUsage);
watch.Reset();
watch.Start();
}
}
}));
}
static void Main(string[] args)
{
int cpuUsage = 50;
int time = 10000;
List<Thread> threads = new List<Thread>();
for (int i = 0; i < Environment.ProcessorCount; i++)
{
Thread t = new Thread(new ParameterizedThreadStart(CPUKill));
t.Start(cpuUsage);
threads.Add(t);
}
Thread.Sleep(time);
foreach (var t in threads)
{
t.Abort();
}
}
For a uniform stressing: Isak Savo's answer with a slight tweak. The problem is interesting. In reality there are workloads that far exceed it in terms of wattage used, thermal output, lane saturation, etc. and perhaps the use of a loop as the workload is poor and almost unrealistic.
int percentage = 80;
for (int i = 0; i < Environment.ProcessorCount; i++)
{
(new Thread(() =>
{
Stopwatch watch = new Stopwatch();
watch.Start();
while (true)
{
// Make the loop go on for "percentage" milliseconds then sleep the
// remaining percentage milliseconds. So 40% utilization means work 40ms and sleep 60ms
if (watch.ElapsedMilliseconds > percentage)
{
Thread.Sleep(100 - percentage);
watch.Reset();
watch.Start();
}
}
})).Start();
}
Each time you have to set cpuUsageIncreaseby variable.
for example:
1- Cpu % increase by > cpuUsageIncreaseby % for one minute.
2- Go down to 0% for 20 seconds.
3- Goto step 1.
private void test()
{
int cpuUsageIncreaseby = 10;
while (true)
{
for (int i = 0; i < 4; i++)
{
//Console.WriteLine("am running ");
//DateTime start = DateTime.Now;
int cpuUsage = cpuUsageIncreaseby;
int time = 60000; // duration for cpu must increase for process...
List<Thread> threads = new List<Thread>();
for (int j = 0; j < Environment.ProcessorCount; j++)
{
Thread t = new Thread(new ParameterizedThreadStart(CPUKill));
t.Start(cpuUsage);
threads.Add(t);
}
Thread.Sleep(time);
foreach (var t in threads)
{
t.Abort();
}
//DateTime end = DateTime.Now;
//TimeSpan span = end.Subtract(start);
//Console.WriteLine("Time Difference (seconds): " + span.Seconds);
//Console.WriteLine("10 sec wait... for another.");
cpuUsageIncreaseby = cpuUsageIncreaseby + 10;
System.Threading.Thread.Sleep(20000);
}
}
}