I am wondering what is the best way to achieve this in Windows Forms - what I need is a window showing time elapsed (1 sec 2 secs etc) up to 90 seconds while code is being executed. I have a timer right now implemented as follows but I think I also need a stopwatch there as well since the Timer blocks the main thread.
static System.Timers.Timer pXRFTimer = new System.Timers.Timer();
static int _pXRFTimerCounter = 0;
private void ScanpXRF()
{
_pXRFTimerCounter = 0;
pXRFTimer.Enabled = true;
pXRFTimer.Interval = 1000;
pXRFTimer.Elapsed += new ElapsedEventHandler(pXRFTimer_Tick);
pXRFTimer.Start();
//START action to be measured here!
DoSomethingToBeMeasured();
}
private static void pXRFTimer_Tick(Object sender, EventArgs e)
{
_pXRFTimerCounter++;
if (_pXRFTimerCounter >= 90)
{
pXRFTimer.Stop();
}
else
{
//show time elapsed
}
}
I'm not sure about mechanics of your app, but time elapsed can be calculated with something like this
DateTime startUtc;
private void ScanpXRF()
{
startUtc = DateTime.NowUtc;
(...)
//START action to be measured here!
}
private static void pXRFTimer_Tick(Object sender, EventArgs e)
{
var elapsed = DateTime.NowUtc - startUtc;
var elapsedSeconds = elapsed.TotalSeconds; // double so you may want to round.
}
Related
I am writing up a C# application using Winforms, and I need to collect some data based on my selection from a comboBox. I also have a start button that enables data collection, and a stop button that halts the data collection.
This is what I am capable of doing right now:
Measure all data from all channels by switching my selection on the comboBox (one channel at a time). The process goes like: select a channel- start button click - wait for data collection - stop button click
But here is what I want to do in code:
Select a channel - start button click - wait for data collection - stop button click
switch to next channel - start button click -wait for data collection - stop button click
................
repeat this process until done.
My question is: what should I adopt to achieve this?
I have been trying to use startButton.PerformClick( ) to enabling the buttons, however, I need to stop for a few seconds in between starting and stopping to wait for data collection.
You may ask why because this is very inefficient, but for some reason the DLL from the third party cannot collect data from all channels at the same time. So i have to manually switch my channel selection from the comboBox in order to collect all data at one go.
Please let me know if you have any suggestions.
private void timer_Tick(object sender, EventArgs e)
{
startButton.PerformClick();
}
private void timer2_Tick(object sender, EventArgs e)
{
stopButton.PerformClick();
}
private void checkAll_CheckedChanged(object sender, EventArgs e)
{
int i = 0;
while (i != 40) //there are a total of 40 channels
{
System.Windows.Forms.Timer mytimer = new System.Windows.Forms.Timer();
mytimer.Interval = 5000;
System.Windows.Forms.Timer mytimer2 = new System.Windows.Forms.Timer();
mytimer2.Interval = 7000;
mytimer.Start();
mytimer.Tick += new EventHandler(timer_Tick);
mytimer2.Start();
mytimer2.Tick += new EventHandler(timer2_Tick);
physicalChannelComboBox.SelectedIndex = i;
i++;
Thread.Sleep(5000);
}
}
Here is a simple routine shell that should help you. This uses a timer to poll if the data is complete (checking a boolean, which is currently set to true for testing). In your case you could probably just set the timers tick value to be the delay you want. If you have a way of knowing when the data is done being collected for the channel, that would be more preferable. This code runs standalone so you can test and configure it before starting to integrate it into your existing code. All it requires is a a listbox for viewing the logs.
public partial class DataCollectorForm : Form
{
private Timer timer = new Timer();
private int numberOfChannels = 40;
private int currentChannelNumber = 0;
private DateTime routineStartTime;
private DateTime routineStopTime;
private DateTime channelStartTime;
private DateTime channelStopTime;
public DataCollectorForm()
{
InitializeComponent();
timer.Interval = 250;
timer.Tick += Timer_Tick;
DataCollectionRoutineStart();
}
private void Timer_Tick(object sender, EventArgs e)
{
// Need to check if data collection for this channel is complete..
//
var isDoneCollectingData = true;
if (isDoneCollectingData)
{
ChannelDataCollectionStop();
currentChannelNumber++;
if (currentChannelNumber >= numberOfChannels)
{
DataCollectionRoutineComplete();
}
else
{
ChannelDataCollectionStart();
}
}
}
public void DataCollectionRoutineStart()
{
routineStartTime = DateTime.Now;
Log("Data Collection Routine Start");
currentChannelNumber = 0;
ChannelDataCollectionStart();
timer.Start();
}
private void ChannelDataCollectionStart()
{
channelStartTime = DateTime.Now;
Log("Data Collection Start : channel " + currentChannelNumber);
}
private void ChannelDataCollectionStop()
{
channelStopTime = DateTime.Now;
Log("Data Collection Stop : channel " + currentChannelNumber + " : elapsed " + (channelStopTime - channelStartTime));
}
private void DataCollectionRoutineComplete()
{
routineStopTime = DateTime.Now;
timer.Stop();
Log("Data Collection Routine Complete : elapsed " + (routineStopTime - routineStartTime));
}
private void Log(string msg)
{
loggingListBox.Items.Add(msg);
}
}
I have a requirement where i need to execute timer at 00:01:00 A.M every day...But i am not getting how to achieve this ..If i am taking Systems time,it can be in different format..
Here is my timer code..
static System.Timers.Timer timer;
timer = new System.Timers.Timer();
timer.Interval = 1000 * 60 * 60 * 24;//set interval of one day
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
start_timer();
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
// Add timer code here
}
private static void start_timer()
{
timer.Start();
}
If you want to start a timer at exactly 00:01:00am do some processing time and then restart the timer you just need to calculate the difference between Now and the next 00:01:00am time slot such as.
static Timer timer;
static void Main(string[] args)
{
setup_Timer();
}
static void setup_Timer()
{
DateTime nowTime = DateTime.Now;
DateTime oneAmTime = new DateTime(nowTime.Year, nowTime.Month, nowTime.Day, 0, 1, 0, 0);
if (nowTime > oneAmTime)
oneAmTime = oneAmTime.AddDays(1);
double tickTime = (oneAmTime - nowTime).TotalMilliseconds;
timer = new Timer(tickTime);
timer.Elapsed += timer_Elapsed;
timer.Start();
}
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
timer.Stop();
//process code..
setup_Timer();
}
What you should do is write your program that does whatever you need it to do, and then use your OS's built-in task scheduler to fire it off. That'd be the most reliable. Windows's Task Scheduler, for instance, can start your app before the user logs in, handle restarting the app if necessary, log errors and send notifications, etc.
Otherwise, you'll have to run your app 24/7, and have it poll for the time at regular intervals.
For instance, you could change the interval every minute:
timer.Interval = 1000 * 60;
And inside your Elapsed event, check the current time:
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (DateTime.Now.Hour == 1 && DateTime.Now.Minute == 0)
{
// do whatever
}
}
But this is really unreliable. Your app may crash. And dealing with DateTime's can be tricky.
You could always calculate it:
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
// Do stuff
start_timer();
}
private static void start_timer()
{
timer.Interval = CalculateInterval();
timer.Start();
}
private static double CalculateInterval()
{
// 1 AM the next day
return (DateTime.Now.AddDays(1).Date.AddHours(1) - DateTime.Now).TotalMilliseconds;
}
Here is a timer implementation which takes an Interval (just like any other timer) and fires exactly when that interval expires, even the machine goes to sleep mode in between.
public delegate void TimerCallbackDelegate(object sender, ElapsedEventArgs e);
public class TimerAbsolute : System.Timers.Timer
{
private DateTime m_dueTime;
private TimerCallbackDelegate callback;
public TimerAbsolute(TimerCallbackDelegate cb) : base()
{
if (cb == null)
{
throw new Exception("Call back is NULL");
}
callback = cb;
this.Elapsed += this.ElapsedAction;
this.AutoReset = true;
}
protected new void Dispose()
{
this.Elapsed -= this.ElapsedAction;
base.Dispose();
}
public double TimeLeft
{
get
{
return (this.m_dueTime - DateTime.Now).TotalMilliseconds;
}
}
public int TimeLeftSeconds
{
get
{
return (int)(this.m_dueTime - DateTime.Now).TotalSeconds;
}
}
public void Start(double interval)
{
if (interval < 10)
{
throw new Exception($"Interval ({interval}) is too small");
}
DateTime dueTime = DateTime.Now.AddMilliseconds(interval);
if (dueTime <= DateTime.Now)
{
throw new Exception($"Due time ({dueTime}) should be in future. Interval ({interval})");
}
this.m_dueTime = dueTime;
// Timer tick is 1 second
this.Interval = 1 * 1000;
base.Start();
}
private void ElapsedAction(object sender, System.Timers.ElapsedEventArgs e)
{
if (DateTime.Now >= m_dueTime)
{
// This means Timer expired
callback(sender, e);
base.Stop();
}
}
}
How to stop a timer after some numbers of ticks or after, let's say, 3-4 seconds?
So I start a timer and I want after 10 ticks or after 2-3 seconds to stop automatically.
Thanks!
You can keep a counter like
int counter = 0;
then in every tick you increment it. After your limit you can stop timer then. Do this in your tick event
counter++;
if(counter ==10) //or whatever your limit is
yourtimer.Stop();
When the timer's specified interval is reached (after 3 seconds), timer1_Tick() event handler will be called and you could stop the timer within the event handler.
Timer timer1 = new Timer();
timer1.Interval = 3000;
timer1.Enabled = true;
timer1.Tick += new System.EventHandler(timer1_Tick);
void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop(); // or timer1.Enabled = false;
}
i generally talking because you didn't mention which timer, but they all have ticks... so:
you'll need a counter in the class like
int count;
which you'll initialize in the start of your timer, and you'll need a dateTime like
DateTime start;
which you'll initialize in the start of your timer:
start = DateTime.Now;
and in your tick method you'll do:
if(count++ == 10 || (DateTime.Now - start).TotalSeconds > 2)
timer.stop()
here is a full example
public partial class meClass : Form
{
private System.Windows.Forms.Timer t;
private int count;
private DateTime start;
public meClass()
{
t = new Timer();
t.Interval = 50;
t.Tick += new EventHandler(t_Tick);
count = 0;
start = DateTime.Now;
t.Start();
}
void t_Tick(object sender, EventArgs e)
{
if (count++ >= 10 || (DateTime.Now - start).TotalSeconds > 10)
{
t.Stop();
}
// do your stuff
}
}
Assuming you are using the System.Windows.Forms.Tick. You can keep track of a counter, and the time it lives like so. Its a nice way to use the Tag property of a timer.
This makes it reusable for other timers and keeps your code generic, instead of using a globally defined int counter for each timer.
this code is quiet generic as you can assign this event handler to manage the time it lives, and another event handler to handle the specific actions the timer was created for.
System.Windows.Forms.Timer ExampleTimer = new System.Windows.Forms.Timer();
ExampleTimer.Tag = new CustomTimerStruct
{
Counter = 0,
StartDateTime = DateTime.Now,
MaximumSecondsToLive = 10,
MaximumTicksToLive = 4
};
//Note the order of assigning the handlers. As this is the order they are executed.
ExampleTimer.Tick += Generic_Tick;
ExampleTimer.Tick += Work_Tick;
ExampleTimer.Interval = 1;
ExampleTimer.Start();
public struct CustomTimerStruct
{
public uint Counter;
public DateTime StartDateTime;
public uint MaximumSecondsToLive;
public uint MaximumTicksToLive;
}
void Generic_Tick(object sender, EventArgs e)
{
System.Windows.Forms.Timer thisTimer = sender as System.Windows.Forms.Timer;
CustomTimerStruct TimerInfo = (CustomTimerStruct)thisTimer.Tag;
TimerInfo.Counter++;
//Stop the timer based on its number of ticks
if (TimerInfo.Counter > TimerInfo.MaximumTicksToLive) thisTimer.Stop();
//Stops the timer based on the time its alive
if (DateTime.Now.Subtract(TimerInfo.StartDateTime).TotalSeconds > TimerInfo.MaximumSecondsToLive) thisTimer.Stop();
}
void Work_Tick(object sender, EventArgs e)
{
//Do work specifically for this timer
}
When initializing your timer set a tag value to 0 (zero).
tmrAutoStop.Tag = 0;
Then, with every tick add one...
tmrAutoStop.Tag = int.Parse(tmrAutoStop.Tag.ToString()) + 1;
and check if it reached your desired number:
if (int.Parse(tmrAutoStop.Tag.ToString()) >= 10)
{
//do timer cleanup
}
Use this same technique to alternate the timer associated event:
if (int.Parse(tmrAutoStop.Tag.ToString()) % 2 == 0)
{
//do something...
}
else
{
//do something else...
}
To check elapsed time (in seconds):
int m = int.Parse(tmrAutoStop.Tag.ToString()) * (1000 / tmrAutoStop.Interval);
I have a sync timer in my app that fires up a function at a given time... now I want to know how much time is left until the next call to that function.
This is my call to the timer:
var syncTime = time.activitylog;
double time = TimeSpan.Parse(syncTime).TotalMilliseconds;
System.Timers.Timer myTimer = new System.Timers.Timer();
myTimer.Elapsed += new ElapsedEventHandler(DisplayTimeEvent);
myTimer.Interval = time;
myTimer.Start();
How do I get the time until next call?
Thanks
You can use another timer, and set the Interval of that the value that you want,exactly a part time of the Interval of original timer.
Then start them Simultaneously,I mean at the same time.
UPDATE :
Maybe this code describes my solution better :
public Form1()
{
InitializeComponent();
}
System.Windows.Forms.Timer trOriginal = new System.Windows.Forms.Timer();
System.Windows.Forms.Timer trRemain = new System.Windows.Forms.Timer();
double remain = 0;
private void button1_Click(object sender, EventArgs e)
{
trOriginal.Interval = 1000;
trRemain.Interval = 1;
trOriginal.Tick += new EventHandler(trOriginal_Tick);
trRemain.Tick += new EventHandler(trRemain_Tick);
trOriginal.Start();
trRemain.Start();
}
void trRemain_Tick(object sender, EventArgs e)
{
remain -= trRemain.Interval;
Console.WriteLine("remain MS to next event : " + remain);
}
void trOriginal_Tick(object sender, EventArgs e)
{
remain = trOriginal.Interval;
}
You can use a System.Diagnostics.Stopwatch to keep track of how much time has passed already and restart the Stopwatch with every tick of your Timer.
Stopwatch watch = new Stopwatch();
private void DisplayTimeEvent(object sender, EventArgs e)
{
watch.Restart();
// Whatever is supposed to happen, when the timer ticks
}
Now whenever you want to know how much time is left until the event is fired next, you can do this:
long timeLeft = myTimer.Interval - watch.ElapsedMilliseconds;
I am using a timer in my code. Status bar updates in tick event on clicking respective button for the time inteval mentioned in properties say one second. Now i want to use the same timer for a different time interval say two seconds for a different oepration. How to achieve that?
Create a second timer. There is nothing to gain from hacking the first timer.
As #Henk noted, Timers are not that expensive. (Especially not compared to fixing hard to maintain code!)
I agree with #Henk and others.
But still, something like this could work:
Example
Int32 counter = 0;
private void timer1_Tick(object sender, EventArgs e)
{
if (counter % 1 == 0)
{
OnOneSecond();
}
if (counter % 2 == 0)
{
OnTwoSecond();
})
counter++;
}
Updated Example
private void Form_Load()
{
timer1.Interval = 1000; // 1 second
timer1.Start(); // This will raise Tick event after 1 second
OnTick(); // So, call Tick event explicitly when we start timer
}
Int32 counter = 0;
private void timer1_Tick(object sender, EventArgs e)
{
OnTick();
}
private void OnTick()
{
if (counter % 1 == 0)
{
OnOneSecond();
}
if (counter % 2 == 0)
{
OnTwoSecond();
}
counter++;
}
Change timer Interval property.
Change the Interval property in every elapsed time. for example, this program process data 30 seconds and sleep 10 seconds.
static class Program
{
private System.Timers.Timer _sleepTimer;
private bool _isSleeping = false;
private int _processTime;
private int _noProcessTime;
static void Main()
{
_processTime = 30000; //30 seconds
_noProcessTime = 10000; //10 seconds
this._sleepTimer = new System.Timers.Timer();
this._sleepTimer.Interval = _processTime;
this._sleepTimer.Elapsed += new System.Timers.ElapsedEventHandler(sleepTimer_Elapsed);
ProcessTimer();
this._sleepTimer.Start();
}
private void sleepTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
ProcessTimer();
}
private void ProcessTimer()
{
_sleepTimer.Enabled = false;
_isSleeping = !_isSleeping;
if (_isSleeping)
{
_sleepTimer.Interval = _processTime;
//process data HERE on new thread;
}
else
{
_sleepTimer.Interval = _noProcessTime;
//wait fired thread and sleep
Task.WaitAll(this.Tasks.ToArray());
}
_sleepTimer.Enabled = true;
}
}