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 :)
Related
I get List of websites I need to loop through and to spend on each certain amount of time. Looping needs to be asynchronous, because on each website music will be played, and that's the main point - to hear the music in that amount of time, and then to load another page and to listen to its music and so on. Also, form need to be available for user actions.
Code I've got so far is this:
public void playSound(List<String> websites)
{
webBrowser.Navigate(Uri.EscapeDataString(websites[0]));
foreach (String website in websites.Skip(1))
{
StartAsyncTimedWork(website);
// problem when calling more times
}
}
private System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();
private void StartAsyncTimedWork(String website)
{
myTimer.Interval = 7000;
myTimer.Tick += new EventHandler(myTimer_Tick);
myTimer.Start();
}
private void myTimer_Tick(object sender, EventArgs e)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new EventHandler(myTimer_Tick), sender, e);
}
else
{
lock (myTimer)
{
if (this.myTimer.Enabled)
{
this.myTimer.Stop();
// here I should get my website which I need to search
// don't know how to pass that argument from StartAsyncTimedWork
}
}
}
}
One way to do this is as below.
Make websites a class field (if it isn't already), so the timer event handler can access this collection.
Add a field to keep track of the current index.
Add a field to prevent re-entrant calls to PlaySounds.
You're using a WinForms timer, which executes on the same thread as the form, so there's no need for InvokeRequired etc.
Some pseudo-code (warning, this is untested):
private bool isPlayingSounds;
private int index;
private List<String> websites;
private Timer myTimer;
private void Form1_Load()
{
myTimer = new System.Windows.Forms.Timer();
myTimer.Interval = 7000;
myTimer.Tick += new EventHandler(myTimer_Tick);
}
public void PlaySounds(List<String> websites)
{
if (isPlayingSounds)
{
// Already playing.
// Throw exception here, or stop and play new website collection.
}
else
{
isPlayingSounds = true;
this.websites = websites;
PlayNextSound();
}
}
private void PlayNextSound()
{
if (index < websites.Count)
{
webBrowser.Navigate(Uri.EscapeDataString(websites[index]));
myTimer.Start();
// Prepare for next website, if any.
index++;
}
else
{
// Remove reference to object supplied by caller
websites = null;
/ Reset index for next call to PlaySounds.
index = 0;
// Reset flag to indicate not playing.
isPlayingSounds = false;
}
}
private void myTimer_Tick(object sender, EventArgs e)
{
myTimer.Stop();
PlayNextSound();
}
I have a Windows.Forms.Timer in my code, that I am executing 3 times. However, the timer isn't calling the tick function at all.
private int count = 3;
private timer;
void Loopy(int times)
{
count = times;
timer = new Timer();
timer.Interval = 1000;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
count--;
if (count == 0) timer.Stop();
else
{
// Do something here
}
}
Loopy() is being called from other places in the code.
Try using System.Timers instead of Windows.Forms.Timer
void Loopy(int times)
{
count = times;
timer = new Timer(1000);
timer.Enabled = true;
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
throw new NotImplementedException();
}
If the method Loopy() is called in a thread that is not the main UI thread, then the timer won't tick.
If you want to call this method from anywhere in the code then you need to check the InvokeRequired property. So your code should look like (assuming that the code is in a form):
private void Loopy(int times)
{
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
Loopy(times);
});
}
else
{
count = times;
timer = new Timer();
timer.Interval = 1000;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
}
I am not sure what you are doing wrong it looks correct, This code works: See how it compares to yours.
public partial class Form1 : Form
{
private int count = 3;
private Timer timer;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Loopy(count);
}
void Loopy(int times)
{
count = times;
timer = new Timer();
timer.Interval = 1000;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
count--;
if (count == 0) timer.Stop();
else
{
//
}
}
}
Here's an Rx ticker that works:
Observable.Interval(TimeSpan.FromSeconds(1))
.Take(3)
.Subscribe(x=>Console.WriteLine("tick"));
Of course, you can subscribe something more useful in your program.
you may have started the timer from another thread, so try invoking it from the correct thread.
for example, instead of:
timerX.start();
Use:
Invoke((MethodInvoker)delegate { timerX.Start(); });
Check if your timer in properties is enabled.
Mine was false and after setting to true it worked.
If you are using Windows.Forms.Timer then should use something like following.
//Declare Timer
private Timer _timer= new Timer();
void Loopy(int _time)
{
_timer.Interval = _time;
_timer.Enabled = true;
_timer.Tick += new EventHandler(timer_Elapsed);
_timer.Start();
}
void timer_Elapsed(object sender, EventArgs e)
{
//Do your stuffs here
}
If you use some delays smaller than the interval inside the timer, the system.timer will execute other thread and you have to deal with a double thread running at the same time. Apply an InvokeRequired to control the flow.
Could any one help me to stop my timer in windows form C3 application? I added timer in form using designer and interval is set as 1000; I would like to do some actions after 5 seconds of waiting after button click. Please check the code and advise me. Problem now is I get MessageBox2 infinitely and never gets the timer stop.
static int count;
public Form1()
{
InitializeComponent();
timer1.Tick += timer1_Tick;
}
public void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
while(count>5)
{
....dosome actions...
}
}
private void timer1_Tick(object sender, EventArgs e)
{
count1++;
MessageBox.Show("Messagebox2");
if (count1 == 5)
{
//timer1.Enabled = false; timer1.Stop();
((System.Timers.Timer)sender).Enabled = false;
MessageBox.Show("stopping timer");
}
}
I would render the count useless and just use the timer 1 interval property and put your actions in the timer1_Tick event.
public void button1_Click(object sender, EventArgs e)
{
timer1.Interval = 5000;
timer1.Enabled = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Enabled = false;
MessageBox.Show("stopping timer");
// Your other actions here
}
You are incrementing count1 and checking count.
while(count1 > 5)
{
...dosome actions...
}
Which Timer do you use? Because C# supports class Timer from two different namespaces. One is from Forms, the other is from System.Timers. I would suggest you to use the other one - System.Timers.Timer.
Timer t = new Timer(20000); // created with 20seconds
t.Enabled = true; // enables firing Elapsed event
t.Elapsed += (s, e) => {
\\do stuff
};
t.Start();
In this short code you can see how the timer is created and enabled. By registering to the Elapsed event you explicitly say what to do after the time elapses. and this is done just once. Of course, there are some changes needed in case user clicks button before your limit is reached. But this is highly dependent on behavior of the action you demand.
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);
}
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);
}