I have an app that runs several timers.
The first is a heartbeat timer, HB_Timer, which fires off a backgroundworker at the set interval which runs a sql command to register a 'heartbeart'.
The second is a reinit timer, Reinit_Timer, which again fires off a backgroundworker to query global settings from the database and, if the value for heartbeat interval has changed, stops HB_Timer, changes HB_Timer.Interval accordingly and then restarts HB_Timer.
I've amended the code below slightly to put it in its most simplistic format.
The heartbeat interval in the DB is saved in seconds, so i multiply by 1000 to get ms before applying the interval...
Public Function Endpoint_ReInit()
Try
HB_Timer.Stop()
hb_interval = ReadSQLValue(<the data i need to read...>)
If hb_interval > 0 Then HB_Timer.Interval = (hb_interval * 1000)
HB_Timer.Start()
For some reason, once the timer is stopped, it wont start again programatically, and I can't see why.
I've added console.writeline on the tick event of the timer and on firing the backgroundworker... both work before it is stopped and then restarted and then neither work (obviously, if the first doesnt then the second definitely wont).
I wondered if it was going to quickly so have tried sleeping for periods between stopping and starting, but that didn't work.
I even tried adding a temp button on my form to see if the timer could be manually restarted, and that doesn't work either.
I have error handling on all my functions etc and no exceptions are thrown.
I'm at a bit of a loss.... can anyone help point me in the right direction?
At a guess the value returned from the SQL query is large, so it's not that the timer is stopped, it's just that it is taking a very long time before it ticks.
Or something crashes in your backgroundworker and thus your timer.Start() is never called (the call to ReadSQLValue() never returns). If ReadSQLValue() uses a BackgroundWorker, though I'm not really sure how you're managing the sync/async mixing, be aware that when a BackgroundWorker experiences an exception in DoWork() it doesn't may not end up in your code at the time it occurs. The BGW just fires the RunWorkerCompleted event with an EventArgs that has an exception in the Error property)
When I work with timers I tend to set them to some low interval, say 1 second, and if I want something to happen every minute for one process and two minutes for another I have a couple of ints that count down from 60/120 respectively and when they hit 0, I do the processes, and reset the ints back to 60/120. I don't stop/start/change the timer interval
Related
How do I track what events are currently 'Active' or currently being handled while stepping through the code.
The Issue
While I was debugging code (stepping through it) within a rather large application, all of a sudden I found that the code that was being run was running through code in functions that had nothing to do with the code I was troubleshooting. It took me a considerable amount of time to figure out why I found myself stepping through code in functions that were way outside the code I was debugging.
Turns out, at the start of the application, handlers are added to certain controls as well as timer controls. The timer control triggers an event every 5 minutes or so. There were other events being triggered when certain actions were taken, however I had no idea what was causing the debugger to enter into certain functions due to the fact that there was no indication or 'prompt' telling me an Event was Triggered and that was why I was now stepping into other functions.
How do I become aware of what is happening when events are triggered in the manner I mentioned above?
Note
This is not a question about how to add handlers or remove handlers in code.
So basically timers are still running in the same thread as the main logic. every time a function/Event is done and the Window steps into the waiting part in which unser input is read and events are started, timers will trigger. they will not run while other events are busy. If you use Background Worker or start second threads. they will run in between you current steps and the visual studio will jump from one to another. there is a thread window to keep track of all active threads but this only gives a clue. sometimes its still annoying to jump from one to another function. My advice is to use a debugger-hidden attribute on those functions that keep on bothering you.
How to find the Thread window:
How can I view Threads window in Visual studio?
How to use Debugger Hidden:
https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.debuggerhiddenattribute?redirectedfrom=MSDN&view=netframework-4.7.2
and
https://social.msdn.microsoft.com/Forums/vstudio/en-US/cf20736c-cbfb-4919-b495-ea9a9235f9e5/debuggerhiddenattribute-example?forum=csharpgeneral
I have a function that runs an sql query for data that may or may not be there. Since I need to run this function continually until it returns the proper value how can I run a progress bar until the loop finishes.
status = Logic.ProcessResource(currentInstance)
While status.woID.Count <= 0
status = Logic.ProcessResource(currentInstance)
End While
How can I run this and show another form with a progress bar until the loop exits?
My comments as an answer...
Put that code into a different thread, then use a ProgressBar in "Marquee" mode to indicate an operation that is ongoing, but has no known ending time.
Yes...but you still need to put the query/loop in a different thread...otherwise the main UI thread will to be to busy to animate and remain responsive to the user.
Look at the BackgroundWorker control, or using a Task, with Async/Await.
You'd show the form, start the worker, wait for worker to finish, then close the form. The BackgroundWorker() has UI friendly events like RunWorkerCompleted that are already marshaled to the UI thread for you.
Im using some custom control in vb.net, where I have a boolean property that, whenever it changes, it starts a timer if it's value is false or stops if it's true.
If the timer runs for several seconds, it raises a messagebox that warns of a problem happening.
The problem is that this messagebox shows even in design time. As I have traced, the default value for the property is false when the control loads in the winform in design time, it seems it starts the timer and when it ends raises the messagebox, this happens whenever I open the project or rebuild it.
I don't get why this behaviour, as this should only happen at run time but it's driving me crazy, I have tried starting the timer directly when the property changes in the setter and creating "onpropertychanged" events, but this still happens in design time.
Anyone has an idea of how to get rid of this or how to solve it to avoid this of happening, is really disturbing that things happens when the program isn't even running.
Thanks in advance.
Regards
The common way is to use the DesignMode property of the control.
true if the Component is in design mode; otherwise, false.
So in your property, before starting the timer, first check if DesignMode is False.
I have several froms in my application. When application starts, a timer starts for 30 minutes.
I want to show the remaining time using a popup window, message or whatever, on whichever form the user is at that time.
Please advise how to do it.
Thanks
Furqan
The timer objects in the .net framework do not give access to the time already elapsed or remaining.
However when your application starts you will can create and start a stop watch.
private _sw as System.Diagnostics.Stopwatch = System.Diagnostics.Stopwatch.StartNew()
At any time you can then call the following code which you can subtract from your 30 minutes
_sw.Elapsed.TotalSeconds
To show this time constantly on a form you may need a second timer to update the screen that queries this value.
I have three events to fire on button click.
after running the first event i want to wait for 30sec to wait for nex event to fire.
how i can wait( i mean looping for 30 secs).
Thanks,
Nag
You can try this to your code directly:
MessageBox.Show("Test") ' Execute your method 1
System.Threading.Thread.Sleep(30000)
MessageBox.Show("Test2") ' Proceed with the other one :)
If you wait on the UI thread you'll block the whole UI and Windows will show your application as non-responding.
Better to:
Update the UI to show it is busy, including disabling controls to block user input.
Use a timer control (details depend on WinForms or WPF) to trigger an event after the time delay
Do the work in the timer's event handler.
If the work is CPU or IO intensive (ie. likely to block for more than a few tens of milliseconds) then perform the work in the threadpool (eg. BackgroundWorker component). Remember you'll need to use Control.Invoke to make any changes to the UI from the worker thread.
You can use Thread System.Threading.Thread.Sleep(30000); to hold execution.
use a timer for it and set an interval of 30 seconds to timer (1sec = 1000)
timer1.Interval=30000