C# EvenHandler only updates once - c#

I'm trying to get more familiar with eventhanlders, but my current even only updates once, I want it to update until I close the application.
This is my code:
private static event EventHandler Updater;
Updater += Program_updater;
Updater.Invoke(null, EventArgs.Empty);
Application.Run();
private static void Program_updater(object sender, EventArgs e)
{
KeyUtils.Update();
Framework.Update();
}
But like I said, it will only update once, I want it to update until I close my application. I know I can just do a While(true) but I rather not.

I think you want a Timer here:
Timer aTimer = new System.Timers.Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += Program_updater;
// Have the timer fire repeated events (true is the default)
aTimer.AutoReset = true;
// Start the timer
aTimer.Enabled = true;
Specify callback:
private void Program_updater(Object source, System.Timers.ElapsedEventArgs e)
{
KeyUtils.Update();
Framework.Update();
}
Now every 2 seconds (or specify any other interval) callback OnTimedEvent will be called.

It is absolutely normal that your event is fired only once because the application starts only once.
What you acctualy need is to set up a timer and do some work on its tick.
Please have a look on example in answer for that question Simple example of the use of System. Timers. Timer in C#

Well it only updates once since you only invoke it once (I don't really get the context where your code runs since you both declare a static variable and invokes it on the same scope which is impossible).
If you want something to occur periodically you should use Timer, or in some cases AutoResetEvent/ManualResetEvent.
EventHandlers should be used only when you work as event driven which mean you want your handler to invoke When something happens
Here an example for [System.Timers.Timer][2] with your handler:
//Invoke every 5 seconds.
Timer timer = new Timer(5000);
//Add your handler to the timer invocation list.
timer.Elapsed += Program_updater;
//Start the timer.
timer.Start();
Also you need Program_update's signature to look like that:
private void Program_updater(object source, ElapsedEventArgs e)

Related

Throttle an Event Handler

In my WPF application, I have an event handler that gets called on the MouseEnter event of my UI element:
myUiElement.MouseEnter += myEventHandler
I would like to throttle myEventHandler so it doesn't get called more than once every second. How can I do this? Is Rx the best approach just for this? I'm using .NET 4.0 if it makes a difference.
Also, I need to make sure that the MouseLeave event always gets called before the next MouseEnter event; do I need to manage this on my own? Or is the framework already designed so that MouseLeave events will always be called before the next MouseEnter event? What if I have asynchronous code in these event handlers?
Using Rx, you want to use the Sample method or Throttle.
Something like this should work (untested):
Observable
.FromEventPattern<TextChangedEventArgs>(myUiElement, "MouseEnter")
.Sample(TimeSpan.FromSeconds(1))
.Subscribe(x => ... Do Stuff Here ...);
The difference between Sample and Throttle is that Sample will take a value every 1 second no matter when the last value was taken, whereas Throttle will take a value and then wait another 1 second before taking another.
It probably depends on what you are shooting for...
You could use reactive extensions, but you could accomplish this just as easily with a timer.
Set a flag along with a Timer. When the timer tick event fires, set the flag to false, disable the timer, and run the code for your event. Then, in your control event handlers, have the handler code skipped if the flag is set.
bool flag;
DispatcherTimer timer;
public constructor()
{
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += (s,e) => {
flag = false;
timer.Stop()
DoThrottledEvent();
}
}
void mouse_enter(object sender, MouseEventArgs args)
{
if(!flag)
{
flag = true;
timer.Start();
}
}
void DoThrottledEvent()
{
//code for event here
}
Reactive extensions introduces an extra dependency, but they are a bit of fun. If you are interested, go for it!
Another approach would be to use a private field to keep track of the "time" when the last mouse event occurred, and only continue processing if that time was more than one second ago.
DateTime _lastMouseEventTime = DateTime.UtcNow;
void OnMouseEnter(object sender, MouseEventArgs e)
{
DateTime now = DateTime.UtcNow;
if (now.Subtract(_lastMouseEventTime).TotalSeconds >= 1)
{
// do stuff...
}
_lastMouseEventTime = now;
}
This ensures that "stuff" gets done at least one second apart, which is what I think you were asking for.

What is the best way to implement a "timer"? [duplicate]

This question already has answers here:
How do you add a timer to a C# console application
(12 answers)
Closed 3 years ago.
What is the best way to implement a timer? A code sample would be great! For this question, "best" is defined as most reliable (least number of misfires) and precise. If I specify an interval of 15 seconds, I want the target method invoked every 15 seconds, not every 10 - 20 seconds. On the other hand, I don't need nanosecond accuracy. In this example, it would be acceptable for the method to fire every 14.51 - 15.49 seconds.
Use the Timer class.
public static void Main()
{
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 5000;
aTimer.Enabled = true;
Console.WriteLine("Press \'q\' to quit the sample.");
while(Console.Read() != 'q');
}
// Specify what you want to happen when the Elapsed event is raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("Hello World!");
}
The Elapsed event will be raised every X amount of milliseconds, specified by the Interval property on the Timer object. It will call the Event Handler method you specify. In the example above, it is OnTimedEvent.
By using System.Windows.Forms.Timer class you can achieve what you need.
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
t.Interval = 15000; // specify interval time as you want
t.Tick += new EventHandler(timer_Tick);
t.Start();
void timer_Tick(object sender, EventArgs e)
{
//Call method
}
By using stop() method you can stop timer.
t.Stop();
It's not clear what type of application you're going to develop (desktop, web, console...)
The general answer, if you're developing Windows.Forms application, is use of
System.Windows.Forms.Timer class. The benefit of this is that it runs on UI thread, so it's simple just define it, subscribe to its Tick event and run your code on every 15 second.
If you do something else then windows forms (it's not clear from the question), you can choose System.Timers.Timer, but this one runs on other thread, so if you are going to act on some UI elements from the its Elapsed event, you have to manage it with "invoking" access.
Reference ServiceBase to your class and put the below code in the OnStartevent:
Constants.TimeIntervalValue = 1 (hour)..Ideally you should set this value in config file.
StartSendingMails = function name you want to run in the application.
protected override void OnStart(string[] args)
{
// It tells in what interval the service will run each time.
Int32 timeInterval = Int32.Parse(Constants.TimeIntervalValue) * 60 * 60 * 1000;
base.OnStart(args);
TimerCallback timerDelegate = new TimerCallback(StartSendingMails);
serviceTimer = new Timer(timerDelegate, null, 0, Convert.ToInt32(timeInterval));
}

start a timer from different thread in c#

Hi i have stepped into some problem related to timer.
hope somebody can help..
I have a windows form containing a button
when i click on that button i start a parameterised thread
Thread thread1 = new Thread(new ParameterizedThreadStart( execute2));
thread1.Start(externalFileParams);
the code inside the thread executes very well
at the last line of this thread i start a timer
.
public void execute2(Object ob)
{
if (ob is ExternalFileParams)
{
if (boolean_variable== true)
executeMyMethod();//this also executes very well if condition is true
else
{
timer1.enabled = true;
timer1.start();
}
}
}
}
5 but the tick event of the timer is not fired
I am working on VS2008 3.5 framework. I have dragged the timer from toolbox and set its Interval to 300 also tried to set Enabled true/false
method is timer1_Tick(Object sender , EventArgs e) but its not fired
can anybody suggest what I am doing wrong?
You could try to start the timer this way:
Add in form constructor this:
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 1 second.
aTimer.Interval = 1000;
Add this method to Form1:
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
//do something with the timer
}
On button click event add this:
aTimer.Enabled = true;
This timer is already threaded so no need to start a new thread.
It is true what Matías Fidemraizer says. But, there is a work around...
When you have a control on your form that is invokable (eg. a statusbar), just invoke that one!
C# Code sample:
private void Form1_Load(object sender, EventArgs e)
{
Thread sampleThread = new Thread(delegate()
{
// Invoke your control like this
this.statusStrip1.Invoke(new MethodInvoker(delegate()
{
timer1.Start();
}));
});
sampleThread.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
MessageBox.Show("I just ticked!");
}
System.Windows.Forms.Timer works in a single-threaded application.
Check this link:
http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx
Remarks says:
A Timer is used to raise an event at
user-defined intervals. This Windows
timer is designed for a
single-threaded environment where UI
threads are used to perform
processing. It requires that the user
code have a UI message pump available
and always operate from the same
thread, or marshal the call onto
another thread.
Read more "Remarks" section and you'll find that Microsoft recommends that you use this timer synchronizing it with the UI thread.
I would use a BackgroundWorker (instead of a raw thread). The main thread would subscribe to the worker's RunWorkerCompleted event: The event fires in your main thread when the thread completes. Use this event handler to restart your timer.

Cleaning Up Timers?

The following code hides a form for 10 seconds. Nothing too crazy.
Each time the button is pressed, it creates a new timer object that doesn't stop and just keeps going. My intuition tells me that if you end up pressing this button many times, you'll have a bunch of timers that are running when only one is necessary (or is my assumption incorrect?). Also, if I do need to stop and dispose this timer, would I just send it as an argument in RevealForm or have the timer be a class level variable and just stop/reset it each time?
private void ButtonHide_Click(object sender, EventArgs e) {
this.Visible = false;
System.Timers.Timer t = new System.Timers.Timer();
t.Elapsed += new ElapsedEventHandler(RevealForm);
t.Interval = 10000;
t.AutoReset = false;
t.Start();
}
private void RevealForm(object source, ElapsedEventArgs e) {
InvokeReveal();
}
private void InvokeReveal() {
if (InvokeRequired) {
Invoke(new Action(InvokeReveal));
}
else {
this.Visible = true;
}
}
Thanks much!
Create the timer in the class then call t.start() on each click.
No need to destroy/cleanup/etc. Just recycle the one you have.
Your assumption is correct - testing would have asserted such for you.
You could either:
A) Disable the timer after each execution (per-interval) and enable on click, or,
B) Stop and destroy the timer and create a new one with each click.
Either option will require a little refactoring of your existing code.
As for the second part of the question - how you stop the timer is preferential. in such a small application (if this is its function in entirety) then simply stopping the timer within the event handler (or related method) would just do the trick, though in order to access the Timer instance you would declare it at a higher level in scope (i.e not bound within the scope of the click event handler).
Generally, the first thing you do is stop the timer in your event handler.
If you just want one timer then make it a form level variable, start it in your ButtonHide_Click, then at the top of your RevealForm method, stop the timer.

Quick C# threading class

Got a quick question on creating a C# thread.
It needs to run every 10 minutes
The worker will do work then go into sleep for another 10 minutes
It can also be triggered to run immediately by calling Trigger()
It can be stopped by calling Stop()
I've created one with ManualResetEvent, which is set when Stop() is called. This works well but do I need to create another ManualResetEvent or wait handle in order to be able to trigger the worker immediately?
If by Stop you mean Stop waiting and don't run again then I think a Threading.Timer will be a good (lean) choice.
You can activate a timer with a DoWork() method and a 10 minutes interval. It will use the ThreadPool which seems the best choice here. Trigger() can queue DoWork directly on the Pool and Stop() can deactivate the Timer. DoWork() shouldn't use Sleep() and be suitable for the ThreadPool.
Using a timer here makes sense. Here's a quick code-snippet which I haven't tested.
private System.Timers.Timer _timer = null;
public void Constructor()
{
_timer = new System.Timers.Timer(600000);
_timer.Elapsed += new ElapsedEventHandler(t_Elapsed);
}
public void ForceDoWork()
{
//unsubscribe to timer event, so work dowsnt get fired twice
_timer.Elapsed -= new ElapsedEventHandler(t_Elapsed);
StartWorking();
_timer.Elapsed += new ElapsedEventHandler(t_Elapsed);
}
public void StartWorking()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(WorkToBeDone));
}
private void WorkToBeDone(object state)
{
//work here
}
public void t_Elapsed(object sender, ElapsedEventArgs e)
{
StartWorking();
}
Yes, you'll need another wait handle to force thread to execute. You'll basically have to WaitOne for this handle for 10 minutes, thus either elapsing a timeout or continuing whenever the wait handle becomes signalled.
Don't forget to switch that handle to a non-signalled state, though.

Categories