Time based event in C# - c#

what I want to do is the following:
I got several variables e.g. and when one variable changes in value (from 0 to 1) i want to start a 'time based event'.
public int a = 0;
public int b = 0;
if (a == 1)
{
//"check for two seconds if int b becomes 1 otherwise go back to usual loop"
}
//basically a second if-statement would follow:
if ( b == 1 within 5 seconds)
{
//"go to next step"
}
I realize this is extremely generic, but hopefully you get what I want to do.
If not, I can elaborate.
Thank you for help.

Capsule your variables and start a timer if the variables get changed:
//initialising
Timer T = new System.Timers.Timer(2000); //Timer with two second interval
aTimer.Elapsed += TimerElapsed;
private int a = 0;
public int A
{
get
{
return a;
}
set
{
if (value == 1)
{
T.Start();
}
a = value;
}
}
private void TimerElapsed(Object source, System.Timers.ElapsedEventArgs e)
{
//timer elapsed code
T.Stop();
}
if you change the value of your variable A, the timer gets startet if the new values is 1. After the Timer is elapsed it stops.

Related

how to make a function with a while that doesnt stop the program

I am making a MAUI application. I wanted to make a method that when it starts it shows me random numbers in a label and when I play it back it stops and returns the last number. but the problem is that when it starts the whole program stop because it is in the loop.
how can i make the method "Start" parallel to the program so i can stop it manually?
bool Counting = false;
public int Start()
{
Counting = true;
int n = 0;
while (Counting)
{
n = random.Next(100);
}
return n;
}
public void Stop()
{
Counting = false;
}
use a Timer
using System.Timers;
...
public int Value { get; set; }
...
// fire every 100ms (10x per second)
Timer timer = new Timer(100);
timer.Elapsed += { Value = random.Next(100); };
timer.AutoReset = true;
timer.Enabled = true;
when you want to stop, call timer.Stop();

Preventing multiple View clicks in Android (MonoDroid) using C# lock()

I'm trying to prevent multiple clicks from taking affect, and would like to know if the following logic will cover all possibilities?
Currently, each successive "click" (touch) fires off an additional download.
private object CLICK_LOCK = new System.Object();
public void ViewClickHandler(object o, System.EventArgs a)
{
View clickedView = (View)o;
lock (CLICK_LOCK)
{
if (clickedView.Clickable == false)
{
return;
}
clickedView.Clickable = false;
}
// sets clickedView.Clickable = true when finished
(new DownloadAsyncTask()).Execute();
}
To prevent multiple View clicks in a short time, a better solution is set a limit time for the Button. If the time interval between the two clicks does not exceed the MIN_CLICK_DELAY_TIME, the event will not trigger.
//Prevent multiple clicks in 1 second.
public static int MIN_CLICK_DELAY_TIME = 1000;
private long lastClickTime = 0;
bt.Click += ViewClickHandler;
public void ViewClickHandler(object o, System.EventArgs a)
{
long currentTime = Calendar.Instance.TimeInMillis;
if (currentTime - lastClickTime > MIN_CLICK_DELAY_TIME)
{
lastClickTime = currentTime;
OnNoDoubleClick();
}
}
protected void OnNoDoubleClick()
{
(new DownloadAsyncTask()).Execute();
}

How to calculate the rate of change of a variable over time in C#?

I need to implement an algorithm that adapts to the rate of change of a variable. Lets say I have an integer HumidityPercent and an external sensor feeding data on real time.
I found several ways to detect if my var has changed:
private float HumChange
{
get { return HumidityPercent; }
set
{
HumidityPercent = value;
if (HumidityPercent != 100)
{
// Do what?
}
}
}
I have a timer (a stopwatch) to calculate milliseconds passed. Thing is: How can I invoke a change in a new variable to store both milliseconds and the new value?
private double newHum = (HumidityPercent, timer.TotalMilliseconds);
But after that how can I differentiate?
Any help would be appreciated.
If you need the rate of change then you need to have three things:
The original value.
The new value.
The time difference between these values.
If you have a timer running then the first time it fires all it needs to do is store the humidity.
The next time it fires it needs to move the "current" value into the "previous" value, update the "current" value and do the rate of change calculation.
So if you have your values as nullable doubles you can test to see if you have a previous value or not:
private double? previous;
private double current;
private double rateOfChange;
private void TimerTick(....)
{
if (previous == null)
{
current = GetHumidity();
}
else
{
previous = current;
current = GetHumidity();
rateOfChange = (current - previous) / time;
}
}
After a thorough search (and a lot of learning on my side) I built up on #ChrisF code and made a consise snipet that is efficient and elegant.
public void InitTimer()
{
timer = new System.Timers.Timer();
timer.Enabled = true;
timer.Elapsed += timer_Tick;
timer.Interval = 200;
}
public void timer_Tick(object sender, System.Timers.ElapsedEventArgs e)
{
timer.Enabled = false;
System.Threading.Interlocked.Increment(ref current);
if (current == 0)
{
current = HumidityPercent;
}
else
{
previous = current;
current = HumidityPercent;
RateOfChange = (current-previous)/5;
Thread.Sleep(200);
}
timer.Enabled = true;
}
Noticed that I have to call the InitTimer method once, so I used:
if (firstrun == true)
{
InitTimer();
firstrun = false;
}
Also notice that I have sandwiched the tick in a stop-start event, put a Thread.Sleep and also added the very handy and efficient System.Threading.Interlocked.Increment(ref current).
Thank you all for your contribution!

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

How do I subscribe to raised events and printing together?

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

Categories