Can a c# timer call the .stop function on itself? - c#

Whenever I try to do something like this the timer doesnt stop:
private void timer1_Tick(object sender, EventArgs e)
{
if ((addedToFriendsCounter == 4) || (followJobFinished))
{
//stop the timer
}
}
Any suggestions?

Yes, no problem. A comment can't stop a timer. Use
timer1.Stop();
or
((Timer)sender).Stop();

There's no problem stopping the timer from within the Tick event handler. What the heck is addedToFriendsCount and followJobFinished? Your error is either with one of these or the code for //stop the timer.

Yes, there is no problem stopping the timer from the Tick event. The event runs in the main thread, so there is no cross-thread problems when you access the Timer control.
You can stop the timer either by calling the Stop method or by setting the Enabled property to false.

Related

System.Windows.Forms.Timer is NOT Firing Tick Event Inside Foreach Block

I have a System.Windows.Forms.Timer associated with my main form. I need this timer to fire every 1000ms so that some work can be performed. The Timer.Enabled property is set to true in the Form.Shown event and the interval is set to 1000.
The Timer.Tick event does fire about every second for the most part. However, the Tick events stop firing when my application is executing a foreach statement. I have tried Thread.Sleep but, that did not help. Does anyone have any suggestions? The code that handles my Timer.Tick event is wrapped with exception handling and I have verified that the event stops firing in the debugger during execution of the foreach block. Additionally, my application is not multi-threaded at this time. Any suggestions?
If you are keeping the UI thread busy in a loop, then no, the timers Tick handler won't be able to execute. If you have a long running loop, push it onto a background thread. Sleep won't help because that also blocks the UI thread. There are other timers that don't fire on the UI thread (System.Timer), but if your tick needs access to the UI, then that won't actually help you if the UI thread is still busy.
Implementation of the System.Timers.Timer might look something like this:
var timer = new System.Timers.Timer();
timer.Interval = 1000; // every second
timer.Elapsed += TimerTick;
...
private void TimerTick(object state, System.Timers.ElapsedEventArgs e)
{
// do some work here
Thread.Sleep(500);
var reportProgress = new Action(() =>
{
// inside this anonymous delegate, we can do all the UI updates
label1.Text += string.Format("Work done {0}\n", DateTime.Now);
});
Invoke(reportProgress);
}

How to Pause without Blocking the UI

I have a click event which causes the phone to vibrate once a button is clicked. This generally works great, except sometimes the vibration doesnt stop until I completely close the application. I would like to give the application time to complete its vibration and then continue with the rest of the method, but I do not want to block the UI at all. How might I accomplish this
MainPage.xaml.cs
void newButton_Click(object sender, EventArgs e)
{
//Button vibration
if (Settings.EnableVibration.Value) //boolean flag to tell whether to vibrate or not
{
VibrateController.Default.Start(TimeSpan.FromMilliseconds(100));
//place vibration stop here?
}
this.NavigationService.Navigate(new uri("/NewPage.xaml", UriKind.Relate));
}
I have already tried VibrationController.Default.Stop(); but this completely eliminates the vibration all together. Is there a way to simply wait until after the vibration has completed to then navigate to a new page, or do whatever other action the method should perform? Any reccomendations or advice on this implementation or other suggestions?
You can use asynchrony to prevent blocking the UI. Rather than actually blocking the UI thread you need to schedule an action to happen again 100ms from now. Adding a continutation to a Task.Delay call can do just that:
void newButton_Click(object sender, EventArgs e)
{
Action navigate = () =>
this.NavigationService.Navigate(new uri("/NewPage.xaml", UriKind.Relate));
if (Settings.EnableVibration.Value) //boolean flag to tell whether to vibrate or not
{
VibrateController.Default.Start();
Task.Delay(100).ContinueWith(t =>
{
VibrationController.Default.Stop();
navigate();
});
}
else
navigate();
}
.NET wraps this functionality up conveniently in the BackgroundWorker class.
private void SomeMethod()
{
// Create backgroundworker
BackgroundWorker bw = new BackgroundWorker();
// Attach event handler
bw.DoWork += bw_DoWork;
// Run Worker
bw.RunWorkerAsync();
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
// Do background stuff here
}
It also has support for progress updates and triggers an event on completion, as far as I know, this functionality extends to windows phone. All of this is covered in the MSDN article.
I would guess what you want to do is call vibrate in the BackgroundWorker, and you can listen for the RunWorkerCompletedEvent which will fire when it is finished. Also, you can happily pause this "thread" and it will not interfere with the UI.

C# WinForms: activating a timer from a thread

public void timer_thing()
{
Thread timer = new Thread(new ThreadStart(() =>
{
Thread.Sleep(500);
if (is_mouse_down)
timer1.Enabled = true;
}
));
timer.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
//some stuff happens here
}
As you can see I want the thread to activate the timer. But the timer doesn't activate. I guess this is not the right way. Or i'm missing something.
It could be that is_mouse_down is false whenever the thread hits that instruction. The thread is not going to magically wait for it to turn true.
However, you have another, bigger problem to worry about. The thing is you cannot touch any UI element from a worker thread or any other other than the UI thread. This includes the System.Windows.Forms.Timer. All sorts of undefined chaos may ensue. Your application may fail unpredictably and spectacularly.
It is not really clear to me why a thread is needed in the first place. Can you not handle the Control.MouseDown event and enable the timer in the event handler for that event? That is how I would solve the problem.
Your thread isn't waiting for the is_mouse_down event. It just checks after half a second and if it's not the time won't get enabled and the tread closes. Maybe you should try using an event?
You can use AutoResetEvent to automatically trigger it from Button Click handler.
So in thread just set:
autoResetEvent.WaitOne();
timer1.Enabled = true;
and in button click handler:
autoResetEvent.Set();
BTW, why you can not initialize a Timer in the Click handler?
This problem as described in literature has two solutions:
1) Active waiting
2) Notifications
If you want the active waiting solution(which is really an outdated one, your thread should have while loop).
If you want the notification when you should call some method which starts the timer in the mouse down event handler
If you have questions about c# multithreading you should read this article. It is really helpful and will show you AutoresetEvent, ManualResetEvents, Thread Timers, Timers, etc. Really good general article.
You have to pass the timer1_Tick callback when you declare your timer object.

Visual Studio 2008, Timer, c#

If i want my application to do something every 2hr (eg. pop up a message), how do i do that?
Do i program that set of code under onLoad() or somewhere else?
Assuming WinForms.
You should use Windows Timer Class
Drag and drop timer component to your form.
Set interval to 7200000 (2 * 60 * 60 * 1000) milliseconds.
Subscribe to Tick event (the only event that this component has).
private void timer1_Tick(object sender, EventArgs e)
{
MessageBox.Show("Example");
}
The code inside of timer will be triggered every 2 hours, if UI thread is not blocked.
Check the Timer Control and event Tick
Timer.Tick - MSDN
Use the Timer class and set it up when the application starts.

C# Winform looping event on Press Button

I made two buttons which controls scrolling on a DataGrid OnClick. I'll like to execute the code managing the scroll when users stay press on it.
I tried on MouseDown() but the code is execute only one time.
Need help.
When you get a mouse down event, set a timer to start calling a "scroll" callback function every 200ms or so (random guess on the time).
In the timer callback, scroll by one "notch" (however much you make it.)
When you get a mouse up event, stop the timer.
If you don't want to use the timer, you can always spawn a thread when needed. You only have to be careful to use Invoke() mechanism when using the UI controls, which are on the other thread.
Code:
private bool mouseDown = false;
private void buttonScrollUp_MouseDown(object sender, MouseEventArgs e)
{
mouseDown = true;
new Thread(() => {
while (mouseDown)
{
Invoke(new MethodInvoker(() => [DO_THE_SCROLLING_HERE));
Thread.Sleep([SET_AUTOREPEAT_TIMEOUT_HERE);
}
})
.Start();
}
private void buttonScrollUp_MouseUp(object sender, MouseEventArgs e)
{
mouseDown = false;
}
Code snippet above of course lacks some sanity and error cheks.
LP,
Dejan
Main idea is to implement timer, for example every 100ms, and do your logic in tick event. Algorithm can look like:
Capture mouse and start timer in MouseDown event
In MouseMove detect is cursor still over button, if no set flag
In timer tick check flag is mouse over button, and do your scroll logic
Release mouse capture and stop timer in MouseUp event

Categories

Resources