I am really stuck with how to use events in my app. I have two files:
RTimer.cs
SettingsForm.cs
I have a timer set up in RTimer.cs that initializes the timer and sets the interval and such.
I have a method in SettingsForm.cs that needs to do something every time the timer ticks. This file also has a method that sets the timers interval via a SetTimer() method in the RTimer.cs
I cant for the life of me figure out how to get the Tick event to call the method from the other class, or get the method in the other class to subscribe to the Tick event.
You can implement this way :
class SettingsForm
{
public void OnTimerEvent(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
class RTimer
{
Timer timer = new Timer();
public void StartTimer(SettingsForm settingForm)
{
timer.Tick += settingForm.OnTimerEvent;
timer.Interval = 5000;
timer.Enabled = true;
}
}
Related
I want to override the default Elapsed event for the System.Timers.Timer class to easily be able to remove all event listeners when desired. Using Jorge's answer from this question, I came up with the following
class CustomTimer : System.Timers.Timer {
List<ElapsedEventHandler> delegates = new List<ElapsedEventHandler>();
private new event ElapsedEventHandler _elapsed;
public new event ElapsedEventHandler Elapsed {
add {
_elapsed += value;
delegates.Add(value);
}
remove {
_elapsed -= value;
delegates.Remove(value);
}
}
public void RemoveAllEvents() {
foreach (ElapsedEventHandler e in delegates) {
_elapsed -= e;
}
delegates.Clear();
}
}
When I run the service that this is executing in, I can trace through to see that the private Elapsed member is being assigned. However I'm not able to see the event handler actually execute. Did I set this up correctly?
This is how i did it :
public void AddElapsed(ElapsedEventHandler newHandler)
{
base.Elapsed += newHandler;
delegates.Add(newHandler);
}
Then only use AddElapsed() instead of Elapsed +=
Maybe add the following as well:
[Obsolete]
public new event ElapsedEventHandler Elapsed;
public class PacketPoller
{
private Timer m_timer;
public void Start()
{
m_timer = new Timer(OnTick(null), null, 0, 1);
m_timer.InitializeLifetimeService();
}
public Action<Object> OnTick() { }
}
This is my code, however, the timer seems to require a staticmethod, rather than an object-oriented method. What can I do about it? I want to user to be able to create a new Timer and then change it's OnTick to set the method to call. How can I do that?
This is what I've successfully used recently.
DispatcherTimer timer1stDoze = new System.Windows.Threading.DispatcherTimer();
timer1stDoze.Tick += new EventHandler(timer1stDoze_Tick);
timer1stDoze.Interval = new TimeSpan(0, 5, 0);
timer1stDoze.Start();
If you're going to stick with the System.Threading.Timer, have it as you have, but have your PacketPoller have its own event that you'll fire in conjunction:
public class PacketPoller
{
public event EventHandler Tick;
private Timer m_timer;
public void Start()
{
m_timer = new Timer(OnTick, null, 0, 1);
m_timer.InitializeLifetimeService();
}
public void OnTick(object state)
{
var tick = this.Tick;
if (tick != null)
tick();
}
}
Listeners will be wired to your PacketPoller.Tick event rather than the m_timer directly. I'm assuming you don't have a state to bubble through, but if you need to you can pass it through. (notice I modified the method signature of OnTick and your constructor call as well)
I'm guessing that you are using the System.Timers.Timer class.
I would recommend trying with the System.Windows.Forms.Timer class instead. It do not require a static callback function and is a bit easier to work with (easier to debug due to it not being threaded).
This will require a reference to the System.Windows.Forms assembly tho.
timer.Tick += new EventHandler(CallbackFunction);
I have my winforms built in timer:
System.Windows.Forms.Timer timerLoop;
When the timer is started, I want (if possible) to pass this timer an integer value.
timerLoop.Start();
Till now, I only created a general variable that the timer can read and update this variable just before starting my timer.
You can do this two ways (maybe more):
Extend base Timer by creating new one that inherit it:
private class TimerExnteded : Timer
{
public int Value { get; set; }
public TimerExnteded(int value)
{
Value = value;
}
}
and use that value in Tick event.
Use Tag property of Timer
Timer t = new Timer();
t.Tag = 5;
t.Start();
//event
private void t_Tick(object sender, EventArgs e)
{
var timer = sender as Timer;
var value = (timer.Tag as int?) ?? 0;
value++;
timer.Tag = value;
}
Second approach uses boxing/unboxing of value.
You can also use closure:
t.Tick += (s, a) => OnTick(YourValue);
I have two methods, for example Method1 and Method2. How can I invoke Method2 500ms after Method1 completes?
public void Method1()
{
}
public void Method2()
{
}
Use either the Timer or a BackgroundWorker. Timer is probably most appropriate for your brief description unless you want to do something on the UI thread in which case a DispatchTimer is better for you as it calls back on the UI thread.
Example:
public void Run_Method1_Then_Method2_500_Milliseconds_Later()
{
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(500);
timer.Tick += (s, e) =>
{
// do some quick work here in Method2
Method2(timer);
};
Method1(); // Call Method1 and wait for completion
timer.Start(); // Start Method2 500 milliseconds later
}
public void Method1()
{
// Do some work here
}
public void Method2(DispatcherTimer timer)
{
// Stop additional timer events
timer.Stop();
// Now do some work here
}
Task.Factory.StartNew( () =>
{
Methdd1();
Thread.Sleep(500);
Method2();
});
EDIT
Due to the issue highlighted by #spender this code is problematic and could lead to thread starvation (see: http://msdn.microsoft.com/en-us/library/ff963549.aspx). The timer suggested by #HiTech Magic seems a better way to go.
System.Timers.Timer aTimer = new System.Timers.Timer(10000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 60 seconds (60000 milliseconds).
aTimer.Interval = 60000;
//for enabling for disabling the timer.
aTimer.Enabled = false;
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
//disable the timer
aTimer.Enabled = false;
Method2();
}
public void Method1()
{
//some code
aTimer.Enabled = true;
}
public void Method2()
{
}
ive been working on a program. i has 3 classes. 2 of the classes have timers that repeat at different intervals and once one "cycle" of the timer is done it raises an event with a string as return. the 3rd class subscribes to the events from the other two timer classes and prints them to screen. it works great!
but my issue is that it prints them separately. say currently the first timer class runs and then raises "hello" every 2 minutes and the other class "dog" every second. then every time an event is raised it prints the raised event to console. i would want it to instead print "hellodog" every second.
i was thinking: so each time a timer fires it will raise an event and update a string in the "output" class with the current value, then make another timer that goes off every second, this timer will read both the updated strings together as one output like "hellodog". is this possible if it is this is the easiest way i think. how would i achieve this idea?
if it is confusing i will clarify.
namespace Final
{
public class Output
{
public static void Main()
{
var timer1 = new FormWithTimer();
var timer2 = new FormWithTimer2();
timer1.NewStringAvailable += new EventHandler<BaseClassThatCanRaiseEvent.StringEventArgs>(timer1_NewStringAvailable);
timer2.NewStringAvailable += new EventHandler<BaseClassThatCanRaiseEvent.StringEventArgs>(timer2_NewStringAvailable);
Console.ReadLine();
}
static void timer1_NewStringAvailable(object sender, BaseClassThatCanRaiseEvent.StringEventArgs e)
{
var theString = e.Value;
//To something with 'theString' that came from timer 1
Console.WriteLine(theString);
}
static void timer2_NewStringAvailable(object sender, BaseClassThatCanRaiseEvent.StringEventArgs e)
{
var theString2 = e.Value;
//To something with 'theString2' that came from timer 2
Console.WriteLine(theString2);
}
}
public abstract class BaseClassThatCanRaiseEvent
{
public class StringEventArgs : EventArgs
{
public StringEventArgs(string value)
{
Value = value;
}
public string Value { get; private set; }
}
//The event itself that people can subscribe to
public event EventHandler<StringEventArgs> NewStringAvailable;
protected void RaiseEvent(string value)
{
var e = NewStringAvailable;
if (e != null)
e(this, new StringEventArgs(value));
}
}
public partial class FormWithTimer : BaseClassThatCanRaiseEvent
{
Timer timer = new Timer();
public FormWithTimer()
{
timer = new System.Timers.Timer(200000);
timer.Elapsed += new ElapsedEventHandler(timer_Tick); // Everytime timer ticks, timer_Tick will be called
timer.Interval = (200000); // Timer will tick evert 10 seconds
timer.Enabled = true; // Enable the timer
timer.Start(); // Start the timer
}
void timer_Tick(object sender, EventArgs e)
{
...
RaiseEvent(gml.ToString());
}
}
public partial class FormWithTimer2 : BaseClassThatCanRaiseEvent
{
Timer timer = new Timer();
public FormWithTimer2()
{
timer = new System.Timers.Timer(1000);
timer.Elapsed += new ElapsedEventHandler(timer_Tick2); // Everytime timer ticks, timer_Tick will be called
timer.Interval = (1000); // Timer will tick evert 10 seconds
timer.Enabled = true; // Enable the timer
timer.Start(); // Start the timer
}
void timer_Tick2(object sender, EventArgs e)
{
...
RaiseEvent(aida.ToString());
}
}
}
You can use the same event handler for both timers. And construct the output by identifying the senders. (Didn't test the code for syntax errors.)
private static string timer1Value = string.Empty;
private static string timer2Value = string.Empty;
private static FormWithTimer timer1;
private static FormWithTimer2 timer2;
public static void Main()
{
timer1 = new FormWithTimer();
timer2 = new FormWithTimer2();
timer1.NewStringAvailable += new EventHandler<BaseClassThatCanRaiseEvent.StringEventArgs>(timer1_NewStringAvailable);
timer2.NewStringAvailable += new EventHandler<BaseClassThatCanRaiseEvent.StringEventArgs>(timer1_NewStringAvailable);
Console.ReadLine();
}
static void timer1_NewStringAvailable(object sender, BaseClassThatCanRaiseEvent.StringEventArgs e)
{
if (sender == timer1)
{
timer1Value = e.Value.ToString();
}
else if (sender == timer2)
{
timer2Value = e.Value.ToString();
}
if (timer1Value != String.Empty && timer2Value != String.Empty)
{
Console.WriteLine(timer1Value + timer2Value);
// Do the string concatenation as you want.
}
When the events are handled in your example they have no access to information about the other events. If you want to have 2 events that update strings, but you want the handler to print data from both updated strings, you need the event handlers to have access to both of those strings. You can either store them in variables on the event handling class, or make them public properties of the classes that are raising the events. That way in either event handler you have access to the updated strings from other events.