Why is this C# timer code not working? - c#

I need to be able to disable a button for 1.5 seconds at a time for an application I'm writing. An image is displayed, a user clicks a button, and then another image is displayed. I need to make sure that the user doesn't click the button again too quickly.
So, when the image is displayed, I call this function:
//when a new image is displayed, start the timer and disable the 'done' button
//for 1.5 seconds, to force people to stop pressing next so quickly
System.Timers.Timer mTimer;
void TimerStart() {
Done.IsEnabled = false;
mTimer = new System.Timers.Timer();
mTimer.Interval = 1500;
mTimer.Start();
mTimer.Elapsed += new System.Timers.ElapsedEventHandler(TimerEnd);
}
The TimerEnd code looks like:
void TimerEnd(object sender, EventArgs eArgs) {
if (sender == mTimer){
Done.IsEnabled = true;
mTimer.Stop();
}
}
The 'Done.IsEnabled' line gets hit, but the button is not reenabled and the timer doesn't stop firing. What am I doing wrong here? If it matters, this is a WPF app.

Use DispatcherTimer instead
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(someInterval);
timer.Tick += new EventHandler(someEventHandler);
timer.Start();
private void someEventHandler(Object sender, EventArgs args)
{
//some operations
//if you want this event handler executed for just once
// DispatcherTimer thisTimer = (DispatcherTimer)sender;
// thisTimer.Stop();
}

Basically you are trying to debounce the button, to prevent too quick clicks. Rather than use a timer save the previous click time in millis, if the button is clicked again within a short time ignore the next event.

The timer event is raised on a different thread. When working with the winforms controls, you need to make sure you Invoke them from the same thread where they were called.

When working with WPF there is no guarantee that updates made to UI controls on non-UI threads will work as expected. In many cases you will get an exception when you do this.
In your Timer elapsed handler you need to use the BeginInvoke/EndInvoke paradigm and put your button enabling logic in there to ensure that this code runs on the UI thread instead of Begin/End Invoke
There is a SynchnornizationContext available as well which can be accessed by calling SynchronizationContext.Current . You'll need to cache this before you make the timer call since SynchronizationContext.Current will be null in non-UI threads.
This link talks about this as well.

Related

Real-time Zedgraph does not respond

My real-time does not respond any more when I change focus from it to another program. I.e. it gets stuck.
Could you please suggest me a possible reason and/or solution for this.
Because your GUI thread (background) isn't beeing processed, when it looses focus, your Zedgraph isn't updated. If you move a window over the ZedGraph, it isn't replotted. Instead you will see the focused window. That's my first guess. Since I don't know your programming language and code, I will just show the principle in C#.
A timer or a new data event calls a function RealTimeGraph. The clue is that an extra thread besides the GUI thread calls RealTimeGraph. The Systems.Timers.Timer class already does that for you. Which Timer or BackgroundWorker to use depends on your application.
System.Timers.Timer timer = new System.Timers.Timer();
timer.Elapsed += new ElapsedEventHandler(RealTimeGraph)
Public void RealTimeGraph(object sender, EventArgs e)
{
if (this.InvokeRequired)
{
PeriodicUpdateHandler update = new PeriodicUpdateHandler(this.RealTimeGraph);
this.BeginInvoke(periodic_update,sender, e);
}
else
{
Update(); // check if new data for ZedGraph is available
ZedGraph.GraphPane.AxisChange(); // optional, if ZedGraphAxis has to be recomputed
ZedGraph.control.Invalidate(); // optional
ZedGraph.control.Refresh(); // now the update is visible
}
}
Additionaly it might be handy to call RealTimeGraph, if you focus your application again. Just add a new focus event handler.
this.Enter += new System.EventHandler(this.RealTimeGraph);
I hoped to show you the advantages of this concept.
Verbose ZedGraph with timer
General handy examples on codeproject

Timer/Refresh functionality for text box

In my application, I have two text boxes accompanied with two labels: "Connected" and "Not Connected". As seen in my code, if a connection is established, the "Connected" text box will fill with Green, indicating a network connection. It will be red if not.
The functionality of connection detection is working just fine, however, I have to re-open the application for it to detect the change. I am looking for a way to refresh the application every 5-10 seconds or so automatically to detect any change in connectivity. I don't want to flush out the contents of any other field or box, just the color text boxes. A soft polling loop so to speak. How would I go about doing this using the Timer method. Should I create a new thread in which to run the timer and refresh the box?
Thanks.
if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable() == false)
{
noConnect.Select(); //if not connected, turn box red
noConnect.BackColor = Color.Red;
}
else
{
netConnect.Select(); // if connected, turn box green
netConnect.BackColor = Color.Lime;
}
//need to refresh box/application without losing other box/field contents
//in order to constantly check connectivity around 5-10 seconds or so
//constantly check connectivity
Something like this would work
public Form1()
{
InitializeComponent();
var timer = new Timer();
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = 10000; //10 seconds
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
if (your_function_call())
{
netConnect.BackColor = Color.Green;
}
else
netConnect.BackColor = Color.Red;
}
The timer_Tick would be repeatedly called every interval and you can poll your status and update controls. Because the timer call back is called in the UI-thread you can update any UI elements.
From Timer Class
A Timer is used to raise an event at user-defined intervals. This
Windows timer is designed for a single-threaded environment where UI
threads are used to perform processing. It requires that the user code
have a UI message pump available and always operate from the same
thread, or marshal the call onto another thread. When you use this
timer, use the Tick event to perform a polling operation or to display
a splash screen for a specified period of time. Whenever the Enabled
property is set to true and the Interval property is greater than
zero, the Tick event is raised at intervals based on the Interval
property setting.
This solution uses System.Windows.Forms.Timer that calls the tick on UI-thread. If you use System.Timers.Timer the callback won't be on UI-thread.
just create the timer. it well run on his own thread without you doing any thing else.
You can create a timer somewhere in your application
var timer = new System.Timers.Timer();
timer.Interval = 5000; // every 5 seconds
timer.Elapsed = (s, e) => {
// Your code
};
timer.Start();
Note: please be aware that your code in the Elapsed event handler can/will run on another thread!

c# chat window application problem with timer

I'm developing a chat application. For getting frequetly comming request,messages and zone request I'm using one timer and call all methods on timer.now. The problem is that when ever I click on any control in the application this gives me a late response due to the timer running. It first hangs until it completes the timer code then control click event is fire.
So, any help on how to handle this is appreciated, I also tried threading but this didn't help.
Please give me any idea if u have.
Thanks.
Use System.Timers.Timer or System.Threading.Timer instead of the Windows.Windows.Forms.Timer, and inside the Elapced event handler whenever you call methods or properties on UI controls use control.InvokeRequired and control.Invoke.
the problem with the form timer is that it perform the action on UI thread, From msdn:
Windows timer is designed for a single-threaded environment where UI
threads are used to perform processing
Edit: Here is example using System.Timers.Timer:
private System.Timers.Timer _chatTimer = new System.Timers.Timer();
public Form1()
{
InitializeComponents();
_chatTimer.Interval = 1000;//1 seconds
_chatTimer.Elapsed += OnChatTimerElapsed;
_chatTimer.AutoReset = true;
}
private void OnChatTimerElapsed(object sender, System.Timer.ElapsedEventArts e)
{
//code to perform when timer elapsed.
}
Edit2: Another thing to notice that depending on execution time on the elapsed event handler, if the time required to execute the code on it is larger than 1 second then I suggest you to set _chatTimer.AutoReset to false and only start the timer after the previous elapsed event is finished. for example check this.

VB.net forms application... what event to use when loading initial data

I'm writing a forms application. I'm adding a piece that allows you to double click on a row of a datagridview control to open a new form with more details. These additional details are pulled from a database, which takes a bit of time to finish.
If I run the DB query from the form's load event, the form doesn't show up until everything in the load event has completed, which can take several seconds.
I want the form to show up instantly when you double click, and all of the fields to be populated once the data is ready.
Is there an event I should be using other than Load?
The standard way to accomplish this is to use a background worker thread and disable the button until the worker thread completes. There is a complete event you can subscribe to on the background worker.
You should use threading. Kick off a thread to do the data retrieval in the form's load event. Introduction to threading
You should use a BackgroundWorker to load the data in a background thread without freezing the UI.
If you really want to load on the UI thread, you should handle the Shown event.
This is an c# example using BackgroundWorker as the other posts metioned that loads unit definitions from .xml an file and changes the status label when it finishes. I stuck in the form intializer, but maybe it is better to start it in an OnLoad() override.
public MainForm()
{
InitializeComponent();
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerReportsProgress = false;
bw.WorkerSupportsCancellation = false;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
unitsToolStripLabel.Text = "Loading Units";
bw.RunWorkerAsync();
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
...
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
unitsToolStripLabel.Text = string.Format("{0} Units Loaded", Units.UnitLibrary.WorkingSet.Count);
unitsToolStripLabel.LinkBehavior = LinkBehavior.HoverUnderline;
unitsToolStripLabel.Click += new EventHandler(unitsToolStripLabel_Click);
}
Please explain a little more on why you do not want to use threading/backgroundworker?
Whilst the correct way to do this is the BackgroundWorker thread, a quick and dirty method is to start a timer on the Load event and get the data when the timer expires. Say 10ms is enough for the form to be painted, then you can disable the controls and set the cursor busy while you get the data. But this is still going to lock up the UI thread while the database is busy leading to repainting artifacts eg if part of the window is covered, and doesn't allow you to display progress using a progress bar.
You can let the load event finish, then start another method to pull data from your database. The initialization of the UI can be done after the form has completed loading, but make sure your UI controls are disabled while you're initializing them.

Close modal dialog from external thread - C#

I am struggling to find a way to create the Forms functionality that I want using C#.
Basically, I want to have a modal dialog box that has a specified timeout period. It seems like this should be easy to do, but I can't seem to get it to work.
Once I call this.ShowDialog(parent), the program flow stops, and I have no way of closing the dialog without the user first clicking a button.
I tried creating a new thread using the BackgroundWorker class, but I can't get it to close the dialog on a different thread.
Am I missing something obvious here?
Thanks for any insight you can provide.
You will need to call the Close method on the thread that created the form:
theDialogForm.BeginInvoke(new MethodInvoker(Close));
Use a System.Windows.Forms.Timer. Set its Interval property to be your timeout and its Tick event handler to close the dialog.
partial class TimedModalForm : Form
{
private Timer timer;
public TimedModalForm()
{
InitializeComponent();
timer = new Timer();
timer.Interval = 3000;
timer.Tick += CloseForm;
timer.Start();
}
private void CloseForm(object sender, EventArgs e)
{
timer.Stop();
timer.Dispose();
this.DialogResult = DialogResult.OK;
}
}
The timer runs on the UI thread so it is safe to close the form from the tick event handler.
If you really just want a modal dialog then I found this to be the best solution by far: http://www.codeproject.com/KB/miscctrl/CsMsgBoxTimeOut.aspx (read the comments section for a small modification).
If you want to display your own form modally, then the solution from adrianbanks is best.
you can Invoke the close from your background thread

Categories