I have a very simple application, currently only containing two classes - these are "MainActivity.cs" and "NewDate.cs"
MainActivity simply hooks up a button and an editText control, then makes a call to "NewDate.NewTimer()" - this just begins a .NET timer instance.
Inside "OnCreate" I am able to set the value of the EditText successfully when the user clicks the button, however, when the timer expires, I call
SafeDate.MainActivity.SetTimerDoneText("Timer done!");
Using breakpoints I can determine that the application is running through "SetTimerDoneText", but the line
editTimerInfo.Text = Text;
does not work.
Any help would be greatly apprecioated.
Both classes below:
MainActivity.cs
public class MainActivity : Activity
{
static EditText editTimerInfo;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
Button btnNewTimer = FindViewById<Button>(Resource.Id.newDate);
editTimerInfo = FindViewById<EditText>(Resource.Id.editTimerInfo);
btnNewTimer.Click += (sender, e) =>
{
// Translate user's alphanumeric phone number to numeric
Core.NewDate.NewTimer();
// editTimerInfo.Text = "Timer started!"; //this works
};
}
public static void SetTimerDoneText(string Text)
{
//SetContentView(Resource.Layout.Main);//commented out - doesn't work
// EditText editTimerInfo = FindViewById<EditText>(Resource.Id.editTimerInfo); //commented out - doesn't work
editTimerInfo.Text = Text;
}
}
NewDate.cs
public static class NewDate
{
public static void NewTimer()
{
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 5000; //Miliseconds : 5000 = 1 second
aTimer.Enabled = true;
}
// Specify what you want to happen when the Elapsed event is raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
SafeDate.MainActivity.SetTimerDoneText("Timer done!"); //Successfully enters the function in MainActivity.cs but won't set the EditText value
}
}
From what I see, you are basically trying to implement a ViewModel pattern.
Since you are a beginner, this may be a bit complex to grasp, but when you are ready, take a look at some tutorial
From now on, go for something much more simple, and put your logic in your Activity
btnNewTimer.Click += (sender, e) =>
{
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 5000; //Miliseconds : 5000 = 1 sec
aTimer.Enabled = true;
};
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
editTimerInfo.Text = "Timer done!"; //Successfully enters the function in MainActivity.cs but won't set the EditText value
}
I have never played with Timers so I cannot guarantee it will work, but this is already better than using statics.
Check if this works for you
Related
I have a text field in which the user inserts or typing text for further translation into another language. I need to run the function after the user finished typing - how to determine it?
!!! Note the order of settings for the timer
// Create a System.Timers.Timer
System.Timers.Timer aTimer = new System.Timers.Timer();
// On KeyUp, start the countdown
private void richTextBox1_KeyUp(object sender, KeyEventArgs e) {
aTimer.Interval = 1000; // time in ms (1 sec)
aTimer.AutoReset = false; // "false" - calls the event once, "true" - repeatedly
aTimer.Elapsed += OnTimeout; // event binding
aTimer.Enabled = true; // timer run
}
private void OnTimeout(object sender, ElapsedEventArgs e) {
if (InvokeRequired) Invoke(new Action(() => DoneTyping() ));
}
// User is "finished typing", do something
private void DoneTyping() {
// do something
}
Before all. I'm not so good at this and hopefully you will understand it anyway.
Im making a function in my program where it checks to see if a row in a rtb is highlighted. If not, it highlights it.
For this to work I had to use different threads to be able to access the rtb from different places. My problem is that it creates a new "delegate"/instance/thread every time the timer refreshes. I would like to remove the old thread/delegate or replace it with the new.
Because now the program crashes after a while. It's a very small program but after 40 sec i reach over 3gb ram usage.
Thanks in advance!
Haris.
Code:
private void Timer()//Timer for color refresh
{
aTimer = new System.Timers.Timer(300);
aTimer.Elapsed += new ElapsedEventHandler(Form1_Load);
aTimer.AutoReset = true;
aTimer.Enabled = true;
}
private void RefreshColor()//Refreshing the color of selected row
{
this.Invoke((MethodInvoker)delegate
{
if (richTextBox1.SelectionBackColor != Color.PaleTurquoise)
{
HighlightCurrentLine();
}
});
}
private void Form1_Load(object sender, EventArgs e)
{
Timer();
RefreshColor();
What is happening if i am not mistaken is that you are creating and starting new timers exponentially. So your forms loads, Form1_Load method is called. Form1_Load creates a new timer that when elapsed, will call Form1_Load again. As the old timer not being disposed 2 timers are running now that will both create 2 new timers. 4 timers create 4 new so there are 8, 16, 32 and so on...
Basically what you have to do is call other method on timer elapsed:
private void Timer()//Timer for color refresh
{
aTimer = new System.Timers.Timer(300);
aTimer.Elapsed += ATimer_Elapsed;//new ElapsedEventHandler(Form1_Load);
aTimer.AutoReset = true;
aTimer.Enabled = true;
}
private void ATimer_Elapsed(object sender, ElapsedEventArgs e)
{
RefreshColor();
}
private void RefreshColor()//Refreshing the color of selected row
{
this.Invoke((MethodInvoker)delegate
{
if (richTextBox1.SelectionBackColor != Color.PaleTurquoise)
{
HighlightCurrentLine();
}
});
}
private void Form1_Load(object sender, EventArgs e)
{
Timer();
RefreshColor();
Timer(); is only called ones thus creating only one timer.
So I'm trying to make a clicker game and I've set a timer to the Factory upgrade. The cookies update, but in the background.
The label does not update until you click the Main button (to raise cookie count). I tried CookieCount.Refresh() or Refresh() (CookieCount being the label I want to update every second).
public Form1()
{
InitializeComponent();
TRIPLECBTN.Hide();
// Create a timer with a ten second interval.
aTimer = new System.Timers.Timer(10000);
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 2 seconds (2000 milliseconds).
aTimer.Interval = 1000;
aTimer.Enabled = false;
}
public void OnTimedEvent(object source, ElapsedEventArgs e)
{
cookies = cookies + 1;
}
public void button3_Click(object sender, EventArgs e)
{
if (cookies >= 1)
{
FACTORYBTN.Hide();
INFO1.Hide();
COST1.Hide();
PRICE1.Hide();
cookies -= 250;
MessageBox.Show("You have bought Factory!");
aTimer.Enabled = true;
}
}
(there are some lines in between but they aren't important).
Update the label in the OnTimedEvent where you count up your cookies.
public void OnTimedEvent(object source, ElapsedEventArgs e)
{
cookies = cookies + 1;
label.Text = YourText
}
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;
}
}
}
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);
}