So I have a method that has to run every 30 seconds for upto 2 hours.
My code is:
private void btnJSON_Click(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
//Timing Logic
var geTimerDelay = 2;
Stopwatch s = new Stopwatch();
s.Start();
while (s.Elapsed < TimeSpan.FromHours(geTimerDelay))
{
Stopwatch s30 = new Stopwatch();
s30.Start();
while (s.Elapsed < TimeSpan.FromSeconds(30))
{
//Method To Run
}
s30.Stop();
}
s.Stop();
});
}
Am I doing it correctly (that is achieving the time-gap as mentioned) or is there a correct and/or more time - precise way to do it?
I need to know because I am access data from specific urls and sometimes I am getting null values, maybe due to too frequent access.
Thanks.
EDIT: This gave me an idea of not using a timer, for no specific reason.
If you're going to use StopWatch then you need to do the following to actually have it wait 30 seconds between runs.
private void btnJSON_Click(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
//Timing Logic
var geTimerDelay = 2;
Stopwatch s = new Stopwatch();
s.Start();
while (s.Elapsed < TimeSpan.FromHours(geTimerDelay))
{
Stopwatch s30 = new Stopwatch();
s30.Start();
//Method to run
while (s.Elapsed < TimeSpan.FromSeconds(30))
{
}
s30.Stop();
}
s.Stop();
});
}
But you could just replace the internal StopWatch with a call to Thread.Sleep and avoid spiking the CPU.
private void btnJSON_Click(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
//Timing Logic
var geTimerDelay = 2;
Stopwatch s = new Stopwatch();
s.Start();
while (s.Elapsed < TimeSpan.FromHours(geTimerDelay))
{
//Method to run
Thread.Sleep(TimeSpan.FromSeconds(30));
}
s.Stop();
});
}
Note that the second one puts a 30 second gap between runs. Meaning that the time it takes for your method to run is not included in the time between runs unlike the first one.
This gave me an idea of not using a timer, for no specific reason.
Timer is perfectly valid for this use case. The issue in the linked question was the precision of the stopwatch versus timer. You don't need that level of precision (I'm assuming) so there's nothing wrong with using a Timer.
Since you claim to be "accessing data from specific URLs", the variance in latency probably negates any improvement in precision by using Stopwatch.
I would instead focus on figuring out why you are getting null values, and decide what to to about it.
private int x = 0;
public Form1 ()
{
InitializeComponent();
}
private void button1_Click ( object sender, EventArgs e )
{
InitTimer();
}
private void timer1_Tick ( object sender, EventArgs e )
{
bool s = IsFinished();
if (s == true)
textBox1.Text = "true";
}
private void InitTimer ()
{
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = 3000; //30000 is 30 seconds
timer1.Start();
}
private bool IsFinished ()
{
if (++x == 2) //1 min
{
timer1.Stop();
return true;
}
else return false;
}
This is a real quick method of running your function or method a bunch of times controlled by a timer and a count. From How do I measure how long a function is running? , I would say that using a stopwatch is probably more precise and efficient than my dirty counter, but honestly the timing difference between stopwatch and timer is negligible at best unless you need better than milliseconds timing difference.
Related
I have this piece of code:
public void StartTimer(string roomName)
{
var roomTimer = GetRoomTimer(roomName);
var room = GetRoom(roomName);
if (roomTimer == null)
{
//Create a timer with a two second interval.
roomTimer = new System.Timers.Timer(2000);
roomTimer.Elapsed += (sender, e) => MyElapsedMethod(sender, e, room.Item2);
roomTimer.AutoReset = true;
roomTimer.Enabled = true;
_rooms[roomName].Timer = roomTimer;
}
else
{
roomTimer.Start();
roomTimer.AutoReset = true;
roomTimer.Elapsed += (sender, e) => MyElapsedMethod(sender, e, room.Item2);
_rooms[roomName].Timer = roomTimer;
}
}
public void StopTimer(string roomName)
{
var roomTimer = GetRoomTimer(roomName);
roomTimer.Stop();
}
private static void MyElapsedMethod(Object source, ElapsedEventArgs e, TwilioRoomDto room)
{
room.Time += room.Timer.Interval;
}
When timer is started and then when it is stopped and restarted again it does not track time nearly as accurate. It misses by almost double. Why is this the case I am holding time passes in dictionary.
That is just not the correct way to track the amount of time that has passed. If you want accurate time measurement use a stopwatch
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
Thread.Sleep(10000);
stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;
A stopwatch will, depending on platform, be accurate down to sub microsecond.
If that is for some reason not what you want, a better design would be to save the start-time using DateTime.Now, and calculate the difference in time. If you want to stop and restart you can store this difference in a separate TimeSpan each time the timer is stopped. But using DateTime.Now will have worse resolution, about 1-16ms depending on platform.
bool elapsed = false;
private void timerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
elapsed = true;
}
private void WorkerThreadFunction()
{
Timer _timer = new System.Timers.Timer(60000);
_timer.Elapsed += timerElapsed;
_timer.AutoReset = false;
while (!elapsed)
{
// Do something...
Thread.Sleep(50);
}
}
How is the global variable "elapsed" reacting? Is it possible to run more separate WorkerThreads with timers?
Of course it is possible to run more separate WorkerThreads. Each one will have it's own timer. There shouldn't be a problem.
The variable bool elapsed will be set to true by the first Thread that finishes its job, and it will stay true until some other process sets it to false. If you are unlucky some thread might even not start its job because the first on has set your elapsed to true
EDIT:
it seems that your thread job is encapsulated.
So you could actually also just use a stopwatch, if you don't need to access global variables from within the thread
private void WorkerThreadFunction()
{
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
watch.Start();
while(watch.ElapsedMilliseconds < 60000)
{
// Do something...
Thread.Sleep(50);
}
watch.Stop();
}
Can anyone help me?
How can I make a microsecond timer in c#?
Like other timers, I want to do Something in the timer body.
If you are familiar with Stopwatches setting the tick-frequency to micoseconds via:
Stopwatch stopWatch = new Stopwatch();
stopWatch.ElapsedTicks / (Stopwatch.Frequency / (1000L*1000L));
should solve your problem.
Here you can download MicroLibrary.cs:
http://www.codeproject.com/Articles/98346/Microsecond-and-Millisecond-NET-Timer
Example for your problem:
private int counter = 0;
static void Main(string[] args)
{
Program program = new Program();
program.MicroTimerTest();
}
private void MicroTimerTest()
{
MicroLibrary.MicroTimer microTimer = new MicroLibrary.MicroTimer();
microTimer.MicroTimerElapsed +=
new MicroLibrary.MicroTimer.MicroTimerElapsedEventHandler(OnTimedEvent);
microTimer.Interval = 1000; // Call micro timer every 1000µs (1ms)
microTimer.Enabled = true; // Start timer
System.Threading.Thread.Sleep(2000); //do smth 2 seconds
microTimer.Enabled = false; // Stop timer (executes asynchronously)
Console.ReadLine();
}
private void OnTimedEvent(object sender,
MicroLibrary.MicroTimerEventArgs timerEventArgs)
{
// Do something every ms
Console.WriteLine(++counter);
}
}
}
System.Threading.Thread.SpinWait
is also essential for implementing this 'MicroTimer' lo-level class purpose.
My application is set to go to sleep when a notification balloontip is clicked and this process is all looped. This works, but when I awaken my computer, it goes to sleep shortly thereafter (this has a slight time delay, but as this takes as long as it normally takes for my computer to go to sleep, I wouldn't give this any consideration). I've removed this snippet from my overall program, and the program then works perfectly fine, making me think that there's something in this code that makes the computer go to sleep. Furthermore, in case one of the flags controlling the loops is reset, I've reset those flags, but the problem keeps happening. In case (for some strange reason) the boolean operators were impacting it, I've changed them in all the combinations I could, and it still didn't work! I've tried adding in a command to prevent the computer from going to sleep, but that didn't work either. Any suggestions? Much appreciated.
for (; ; )
{
bool for3 = false;
for (; ; )
{
notifyIcon.ShowBalloonTip(10000);
System.Threading.Thread.Sleep(10000);
Application.DoEvents();
if (loopVariable)
for3 = true;
if (for3) break;
System.Threading.Thread.Sleep(60000);
}
loopVariable = false;
for3 = false;
DateTime timeOnSleep = DateTime.Now;
Application.SetSuspendState(PowerState.Suspend, false, false);//this is the annoying code
DateTime timeOnWake = DateTime.Now;
TimeSpan time = timeOnWake - timeOnSleep;
var minutes = time.TotalMinutes;
Math.Round(time.TotalMinutes, MidpointRounding.AwayFromZero);
double dMins = minutes;
try
{
int iNumber = System.Convert.ToInt32(dMins);
}
catch (System.OverflowException)
{
if (dMins >= 40)
break;
}
}
private static bool loopVariable = false;
void notifyIcon_BalloonTipClicked(object sender, EventArgs e)
{
loopVariable = true;
}
If you find yourself using doevents, you're likely doing something wrong. If you needed to run a loop like that use do {} rather than for (;;). In any case, you don't need either of those things. If this isn't supposed to run infinitely, you can disable the timer just before calling Application.SetSuspendState.
void Main()
{
Timer timer = new Timer();
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = 30000; //How often you want to show the tooltip?
timer.Enabled = true;
}
void notifyIcon1_BalloonTipClicked(object sender, EventArgs e)
{
Application.SetSuspendState(PowerState.Suspend, false, false);
}
void timer_Tick(object sender, EventArgs e)
{
notifyIcon1.ShowBalloonTip(10000);
}
I'm trying to create a Windows Form application that searches for a string and has three possible scenarios:
String 1 found - wait
String 2 found - stop
Else - Perform action and wait 1 minute
I am encountering my problem only on the times when it is expected to wait. When this happens, the newTimer_Tick starts to tick every second. I have tried disabling the timer when it ticks and a few other things but none appeared to work. Below is the code:
public void Action(string result)
{
if (result.Contains("string1"))
{
// Check again in 10 + x seconds
int n = new Random().Next(0, 5000);
int newtime = 10000 + n;
newTimer.Tick += new EventHandler(newTimer_Tick);
newTimer.Interval = newtime;
newTimer.Enabled = true;
}
else if (result.Contains("string2"))
{
// Turn off
newTimer.Enabled = false;
}
else
{
// Perform action and tick again in 1min + x seconds
action1();
int n = new Random().Next(0, 5000);
int newtime = 600000 + n;
newTimer.Tick += new EventHandler(newTimer_Tick);
newTimer.Interval = newtime;
newTimer.Enabled = true;
}
}
private void newTimer_Tick(object sender, EventArgs e)
{
Action( result );
}
What have I done wrong?
Each time the following line is called, an new instance of the event handler newTimerTick is added to the invocation list for the Tick event:
newTimer.Tick += new System.EventHandler(newTimer_Tick);
So every time the time tick goes off newTimerTick is going to be called multiple times, which is going to give you unexpected results.
Configure your event handler once only. In the constructor would be a sensible place.
Have you tried to stop the timer with the Timer.Stop method?
Btw: I don't think you need to reassign the Tick event from the newTimer unless you don't create a new Timer everytime.
I think what you were missing is that you have to stop your timer since you don't actually want it to keep for more than one interval. You seem to want to run it once, check on the result and then decide if you want to keep running it or not. Here's the code:
public void action(string result)
{
int n = new Random().Next(0, 5000);
Boolean blActivateTimer = true;
Timer timer = new Timer();
timer.Tick += timer_Tick;
if (!result.Contains("string1") && !result.Contains("string2"))
{
n += 600000;
action1();
}
else
{
if (result.Contains("string1"))
{
n += 10000;
}
else
{
blActivateTimer = false;
}
}
if (blActivateTimer)
{
timer.Start();
}
}
void action1()
{
}
void timer_Tick(object sender, EventArgs e)
{
Timer t = (Timer)sender;
t.Stop();
action(result);
}