How do I subscribe to raised events and printing together? - c#

I have been working on a program that has 3 classes of which 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 is printing them separately. Lets say that the first timer class runs and then raises "hello" every 2 minutes and the other class "dog" every second and every time an event is raised it prints the raised event to console. I would want it to instead print "hellodog" every second and store the value of the first timer(hello) in a private field or something so it still prints to screen even if the timer(the slower 2 minute timer) hasn't been fired. and when the 2 minute timer fires it updates the value to whatever the new one is and that new value get printed to screen until it fires again.
If it is confusing I will gladly clarify. its kind of hard to explain.
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.
}

Correct me if I misunderstand the question, but it sounds like you want to coordinate your response to the two timer events (print "hellodog").
It seems to me that the easiest way to do this is to just use a single timer, and have the timer's event handler count the number of times the handler has been invoked to decide whether to take the once-per-second action, or also take the once-per-two-minutes action.
Since the slow timer is an exact multiple of your fast timer, you would set just one timer that triggers every second, and also do the 2-minute action every 120 invocations of the 1 second timer (120 seconds = 2 minutes).

I think I understand what you want and that is to synchronize the output of both timers. I am afraid there is no way to do it other than to slog through it. Set up a bunch of Boolean variables that track whether each event fired and whether the synchronized message was sent to the output.

This should do what you want.
public static void Main()
{
var timer1 = new FormWithTimer();
var timer2 = new FormWithTimer2();
var value1 = "";
var value2 = "";
Action writeValues = () => Console.WriteLine(value1 + value2);
timer1.NewStringAvailable += (s, e) =>
{
value1 = e.Value;
writeValues();
};
timer2.NewStringAvailable += (s, e) =>
{
value2 = e.Value;
writeValues();
};
Console.ReadLine();
}
Let me know if this is right. Cheers.

The second (quicker) timer should be the only one to print.
The first (slower) timer should only update a string which the second timer will use.
In the 'Output' class (you can put it before Main):
string string1;
and then:
static void timer1_NewStringAvailable(object sender, BaseClassThatCanRaiseEvent.StringEventArgs e)
{
string1 = e.Value;
}
static void timer2_NewStringAvailable(object sender, BaseClassThatCanRaiseEvent.StringEventArgs e)
{
var theString2 = e.Value;
//To something with 'theString2' that came from timer 2
Console.WriteLine(string1 + theString2);
}

Related

Anonymous functions in Timer C#

Why this is do not work?
I am do not understand what is here wrong . . .
public static void Pause_ForCreate(out Timer _T, ref Label _ChangeImageEllipse)
{
Label d = _ChangeImageEllipse;
_T = new Timer(2000);
// _T.Elapsed += EllipseVisible_Tick;
_T.Elapsed += (sender, e) => EllipseVisible_Tick((object)d, e);
_T.AutoReset = false;
_T.Start();
}
private static void EllipseVisible_Tick(object Sender, ElapsedEventArgs E)
{
((Ellipse)((Label)Sender).Content).Visibility = Visibility.Visible;
}
You should use a DispatcherTimer instead of a Timer, because its Tick handler is called in the UI thread (as opposed to an Elapsed handler of a Timer)
Then you don't need to pass the Label as ref parameter, because you don't want to change the reference inside the method. Also, since you are not returning anything you can remove the out from the Timer _T, and return the timer instead. The label d, is unnecessary and you can send the _ChangeImageEllipse directly to the EllipseVisible_Tick method, but since that method only does one small thing, the method might not be needed at all.
I would refactor it like this:
public static DispatcherTimer Pause_ForCreate(Label _ChangeImageEllipse)
{
var t = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) };
t.Tick += (s, e) => _ChangeImageEllipse.Visibility = Visibility.Visible;
t.Start();
return t;
}

Passing a variable to timer_tick

Got a problem at the moment, I'm using a timer to do animations and I want to be able to decide where to start using Start and Stop integers as i'll show below.
private void Button1_Click(object sender, EventArgs e)
{
AnimateKey(0,100);
}
private void AnimateKey(int Start, int Stop)
{
myTimer.Interval = 5;
myTimer.Tick += new EventHandler(myTimer_Tick);
myTimer.Enabled = true;
myTimer.Start();
}
private void myTimer_Tick(object sender, EventArgs e)
{
lock (myTimer)
{
int StartingFrame = Start;
int StopFrame = Stop;
etc...etc..
}
}
Now my problem is that I want to pass the values 0 and 100 to the Timer Tick event but I have no idea on how to go about doing it.
How can I get the Integers 0 and 100 from the button click to the timer tick ?
Just use a lambda when defining the tick event handler to close over the parameters you need:
private void AnimateKey(int Start, int Stop)
{
myTimer.Interval = 5;
myTimer.Tick += (s, args) => myTimer_Tick(Start, Stop);
myTimer.Enabled = true;
myTimer.Start();
}
private void myTimer_Tick(int Start, int Stop)
{
//Do stuff
}
Also note that the Tick event of the Timer that you're using will be fired in the UI thread, so there is no need for a lock; the code is already synchronized.
use a class with all info:
public class TimerInfo
{
public int Start;
public int Stop;
}
store an instance in timer's Tag
myTimer.Tag = new TimerInfo { Start = 0, Stop = 100 };
inside the eventhandler you access this info
myTimer = (Timer)sender;
TimerInfo ti = (TimerInfo)myTimer.Tag;
Somewhat hard to understand what you mean, but let's give it a try.
If you ment you want to pass the integers start and stop to the function TimerTick, you probably dont understand the EventArgs parameter. EventArgs is ment to store the arguements which are relevant to your scenario - and the solution is simple.
class myTimerEventArgs:EventArgs // Declaring your own event arguements which you want to send
{
public int start{get;set;}
public int stop {get;set;}
/*Constructor, etc...*/
}
...
//Making the call inside another class:
myTimer_Tick(this,new myTimerEventArgs(0,100);
However, I could be misunderstanding you; If are talking about counting the ticks until it reaches 100 ticks (/intervals), the solution is a simple function added to the event, which would probably look like this:
int Count = 0;
...
private void Counter(object sender, EventArgs e)
{
Count++;
}
...
private void AnimateKey(int Start, int Stop)
{
myTimer.Interval = 5;
myTimer.Tick += new EventHandler(myTimer_Tick);
myTimer.Tick += new EventHandler(Counter);
myTimer.Enabled = true;
myTimer.Start();
while(Count!=100);
myTimer.Stop();
}
Hope I helped, have a nice day :)

System.Timers.Timer() Firing multiple times due to aggregation of Elapsed Events

I want to have a section of my code start a timer once it's called, and I want this timer to keep running until I quit the whole program. My problem is, each time I call OnSomethingHappens() , the Elapsed events aggregate (despite my effort with -= ) and the timer starts firing one extra time (or at least this is what I think is happening). I have also tried defining the timer within the class, to no avail. Here's the related part of my code:
public override void OnSomethingHappens()
{
Timer aTimer= new System.Timers.Timer();
aTimer.Elapsed -= (sender, e) => DoSomethingElse(sender, e);
aTimer.Stop();
aTimer.Close();
aTimer.Elapsed += (sender, e) => DoSomethingElse(sender, e);
aTimer.Interval = 1000;
aTimer.AutoReset = true; // I want the timer to keep working, but only fire once each time
Console.WriteLine("Enabling Timer aTimer");
aTimer.Start();
}
I cannot use static (not sure how that would help but I saw timers being defined as static in many sources) because this class has many instances, and I want them to have separate timers.
Thank you.
Start your timer without the AutoReset and restart it at the end of the DoSomethingElse.
aTimer.AutoReset = false;
aTimer.Start();
DoSomethingElse(..)
{
// do stuff here
aTimer.Start();
}
if each instance of this class uses his own timer , so static is no needed.
private Timer _aTimer;
public void OnSomethingHappens()
{
if (_aTimer != null)
{
_aTimer.Enabled = true; // start timer
return;
}
_aTimer = new System.Timers.Timer();
_aTimer.Elapsed += DoSomethingElse;
_aTimer.Interval = 1000; // every 1 second
_aTimer.Enabled = true; // start timer
}
private void DoSomethingElse(object sender, ElapsedEventArgs e)
{
_aTimer.Enabled = false; // stop timer
// do w/e you want
}
First thing you should really only create once instance of the timer, and hook up one event listener. With your current code, a new timer is being created, with an event listener, every time the method is called. Instead make the timer a class variable, and hook up the event listener in the constructor.
You can start the timer in the OnSomethingHappens, but what do you want to happen on subsequent calls to the method? Should the timer restart, or just continue?
You would probably also want to make the class IDisposable, or at least provide a Stop method to stop the timer when the application closes.
public class MyClass : MyBaseClass, IDisposable
{
private Timer _timer;
private volatile bool _isStopped = true;
public MyClass()
{
_timer = new Timer();
_timer.Interval = 1000;
_timer.Elapsed = OnTimerElapsed;
}
public void Stop()
{
_isStopped = true;
_timer.Stop();
}
public void Dispose()
{
if (_timer != null)
{
Stop();
_timer = null;
}
}
protected override void OnSomethingHappens()
{
if (_timer.Enabled)
{
// Restart or do nothing if timer is already running?
}
else
{
_isStopped = false;
_timer.Start();
}
}
private void OnTimerElapsed(object sender, EventArgs a)
{
if (_isStopped)
{
// If the Stop method was called after the Elapsed event was raised, don't start a long running operation
return;
}
}
}

Implement multiple timers in C#

I'm working on a windows forms app where I have several so called "services" that poll data from various services like Twitter, Facebook, Weather, Finance. Now each of my services has its individual polling interval setting so I was thinking I could implement a System.Windows.Forms.Timer for each of my services and set its Interval property accordingly so that each timer would fire an event at the preset interval that will cause the service to pull new data preferably async through a BackgroundWorker.
Is this the best way to do it? or will it slow down my app causing performance issues. Is there a better way of doing it?
Thanks!
You can do it with one Timer, just needs smarter approach to interval:
public partial class Form1 : Form
{
int facebookInterval = 5; //5 sec
int twitterInterval = 7; //7 sec
public Form1()
{
InitializeComponent();
Timer t = new Timer();
t.Interval = 1000; //1 sec
t.Tick += new EventHandler(t_Tick);
t.Start();
}
void t_Tick(object sender, EventArgs e)
{
facebookInterval--;
twitterInterval--;
if (facebookInterval == 0)
{
MessageBox.Show("Getting FB data");
facebookInterval = 5; //reset to base value
}
if (twitterInterval == 0)
{
MessageBox.Show("Getting Twitter data");
twitterInterval = 7; //reset to base value
}
}
}
you do not really need BackgroundWorker, as WebClient class has Async methods.
so you may simply have one WebClient object for each of your "service" and use code like this:
facebookClient = new WebClient();
facebookClient.DownloadStringCompleted += FacebookDownloadComplete;
twitterClient = new WebClient();
twitterClient.DownloadStringCompleted += TwitterDownloadComplete;
private void FacebookDownloadComplete(Object sender, DownloadStringCompletedEventArgs e)
{
if (!e.Cancelled && e.Error == null)
{
string str = (string)e.Result;
DisplayFacebookContent(str);
}
}
private void OnFacebookTimer(object sender, ElapsedEventArgs e)
{
if( facebookClient.IsBusy)
facebookClient.CancelAsync(); // long time should have passed, better cancel
facebookClient.DownloadStringAsync(facebookUri);
}

Timer is firing before the elapsed Interval

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);
}

Categories