Anonymous functions in Timer C# - 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;
}

Related

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 :)

Show label text as warning message and hide it after a few seconds?

I have buttons which validate if the user is administrator or not. If the user currently login is not an administrator then label will show as warning message and then hide after a few seconds. I tried using lblWarning.Hide(); and lblWarning.Dispose(); after the warning message, but the problem is, it hides the message before even showing the warning message. This is my code.
private void button6_Click(object sender, EventArgs e)
{
if (txtLog.Text=="administrator")
{
Dialog();
}
else
{
lblWarning.Text = "This action is for administrator only.";
lblWarning.Hide();
}
}
You're going to want to "hide" it with a Timer. You might implement something like this:
var t = new Timer();
t.Interval = 3000; // it will Tick in 3 seconds
t.Tick += (s, e) =>
{
lblWarning.Hide();
t.Stop();
};
t.Start();
instead of this:
lblWarning.Hide();
so if you wanted it visible for more than 3 seconds then just take the time you want and multiply it by 1000 because Interval is in milliseconds.
If you are using UWP XAML in 2020 and your msgSaved label is a TextBlock, you could use the code below:
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(2);
msgSaved.Visibility = Visibility.Visible;
timer.Tick += (s, en) => {
msgSaved.Visibility = Visibility.Collapsed;
timer.Stop(); // Stop the timer
};
timer.Start(); // Starts the timer.
Surely you could just use Thread.Sleep
lblWarning.Text = "This action is for administrator only.";
System.Threading.Thread.Sleep(5000);
lblWarning.Hide();
Where 5000 = the number of miliseconds you want to pause/wait/sleep
The following solution works for wpf applications. When you start timer a separate thread is started. To update UI from that thread you have to use dispatch method. Please the read the comments in code and use code accordingly. Required header
using System.Timers;
private void DisplayWarning(String message, int Interval = 3000)
{
Timer timer = new Timer();
timer.Interval = Interval;
lblWarning.Dispatcher.Invoke(new Action(() => lblWarning.Content = message));
lblWarning.Dispatcher.Invoke(new Action(() => lblWarning.Visibility = Visibility.Visible));
// above two line sets the visibility and shows the message and interval elapses hide the visibility of the label. Elapsed will we called after Start() method.
timer.Elapsed += (s, en) => {
lblWarning.Dispatcher.Invoke(new Action(() => lblWarning.Visibility = Visibility.Hidden));
timer.Stop(); // Stop the timer(otherwise keeps on calling)
};
timer.Start(); // Starts the timer.
}
Usage :
DisplayWarning("Warning message"); // from your code
this function display specific msg on an label for specific time duration including text style
public void show_MSG(string msg, Color color, int d)
{
this.Label.Visible = true;
this.Label.Text = msg;
this.Label.ForeColor = color;
Timer timer = new Timer();
timer.Interval = d;
timer.Tick += (object sender, EventArgs e) =>
{
this.Label.Visible = false;
}; timer.Start();
}

BackGround Thread with timer for application level-WPF Application

I have a wpf application(No MVVM), this application requires several background thread(Runs with specific time interval).
These thread should be on Application Level i.e. if user is on any WPF Window, these threads should be active.
Basically these thread will are using external resources so locking is also required.
Kindly tell me the best way to do this.
If you want to execute an action periodically in a WPF application you can use the DispatcherTimer class.
Put your code as the handler of the Tick event and set the Interval property to whatever you need. Something like:
DispatcherTimer dt = new DispatcherTimer();
dt.Tick += new EventHandler(timer_Tick);
dt.Interval = new TimeSpan(1, 0, 0); // execute every hour
dt.Start();
// Tick handler
private void timer_Tick(object sender, EventArgs e)
{
// code to execute periodically
}
private void InitializeDatabaseConnectionCheckTimer()
{
DispatcherTimer _timerNet = new DispatcherTimer();
_timerNet.Tick += new EventHandler(DatabaseConectionCheckTimer_Tick);
_timerNet.Interval = new TimeSpan(_batchScheduleInterval);
_timerNet.Start();
}
private void InitializeApplicationSyncTimer()
{
DispatcherTimer _timer = new DispatcherTimer();
_timer.Tick += new EventHandler(AppSyncTimer_Tick);
_timer.Interval = new TimeSpan(_batchScheduleInterval);
_timer.Start();
}
private void IntializeImageSyncTimer()
{
DispatcherTimer _imageTimer = new DispatcherTimer();
_imageTimer.Tick += delegate
{
lock (this)
{
ImagesSync.SyncImages();
}
};
_imageTimer.Interval = new TimeSpan(_batchScheduleInterval);
_imageTimer.Start();
}
These three threads a intialized on App_OnStart
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
try
{
_batchScheduleInterval = Convert.ToInt32(ApplicationConfigurationManager.Properties["BatchScheduleInterval"]);
}
catch(InvalidCastException err)
{
TextLogger.Log(err.Message);
}
Helper.SaveKioskApplicationStatusLog(Constant.APP_START);
if (SessionManager.Instance.DriverId == null && _batchScheduleInterval!=0)
{
InitializeApplicationSyncTimer();
InitializeDatabaseConnectionCheckTimer();
IntializeImageSyncTimer();
}
}

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

WPF: Building a Queue in a Thread with Timers

With reference to the Software Project I am currently working on.
I have the below methods that basically move a canvas with a Timer:
DispatcherTimer dt = new DispatcherTimer(); //global
public void Ahead(int pix)
{
var movx = 0;
var movy = 0;
dt.Interval = TimeSpan.FromMilliseconds(5);
dt.Tick += new EventHandler((object sender, EventArgs e) =>
{
if (movx >= pix || movy >= pix)
{
dt.Stop();
return;
}
Bot.Body.RenderTransform = new TranslateTransform(movx++, movy++);
});
dt.Start();
}
public void TurnLeft(double deg)
{
var currAngle = 0;
dt.Interval = TimeSpan.FromMilliseconds(5);
dt.Tick += new EventHandler(delegate(object sender, EventArgs e)
{
if (currAngle <= (deg - (deg * 2)))
{
dt.Stop();
}
Bot.Body.RenderTransform = new RotateTransform(currAngle--, BodyCenter.X, BodyCenter.Y);
});
dt.Start();
}
Now, from another library, these methods are called like such:
public void run()
{
Ahead(200);
TurnLeft(90);
}
Now of course, I want these animations to happen after another, but what is happening is that the dt.Tick event handler of the DispatchTimer is being overwritten when the second method (in this case, TurnLeft(90)) is invoked and thus, only the second method gets executed as it should.
I need to create some sort of queue that will allow me to push and pop methods to that queue so that dt (the DispatchTimer timer) executes them one by one...in the order they are in the 'queue'
Any way I can go about doing this ? Am I on the right track here, or completely off course?
When you call Invoke() or BeginInvoke() on the Dispatcher, the operation will be queued up and run when the thread associated with the Dispatcher is free. So instead of using the Tick event, use the overload of Dispatcher.Invoke that takes a Timespan.
I have fixed this problem by myself. What I did was create a global Queue of type Delegate and instead of executing the methods directly, I add them to this queue.
Then I would have a separate thread in the constructor that will dequeue methods one by one and executing them:
Queue<TimerDelegate> eventQueue = new Queue<TimerDelegate>();
public Vehicle(IVehicle veh, Canvas arena, Dispatcher battleArenaDispatcher)
{
DispatcherTimer actionTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(100) };
actionTimer.Tick += new EventHandler(delegate(object sender, EventArgs e)
{
if (IsActionRunning || eventQueue.Count == 0)
{
return;
}
eventQueue.Dequeue().Invoke(new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(5) });
});
actionTimer.Start();
}
public void TurnRight(double deg)
{
eventQueue.Enqueue((TimerDelegate)delegate(DispatcherTimer dt)
{
IsActionRunning = true;
var currAngle = 0;
dt.Tick += new EventHandler(delegate(object sender, EventArgs e)
{
lock (threadLocker)
{
if (currAngle >= deg)
{
IsActionRunning = false;
dt.Stop();
}
Rotator_Body.Angle++;
currAngle++;
}
});
dt.Start();
});
}

Categories