Hopefully this isn’t too difficult to follow.
I’m currently working on a small timelogging application that runs quietly in the background. Every time the ticker runs down, the application prompts the user to say what he/she was doing since the last prompt. I’ll eventually have the application write the data into a spreadsheet.
One of the options I have so far enables the user to choose whether or not he/she would like to use the default prompting setting (every time a prompt is missed, it stays visible until the next one is created, meaning if the user leaves his/her computer for a while there may be a fair few prompts sitting on the screen waiting to be filled in) or would like to combine all the prompts (every time a prompt is missed and a new one pops up, the old one is closed and the new one covers the time of the old prompt and the new prompt).
The user can also select a tickbox to turn prompts off. When he/she turns prompts back on again, a prompt pops up asking the user to fill in what he/she was doing while prompts were turned off (useful when the user is running fullscreen applications, etc).
My problem is, when I try to generate the prompts, they don’t display correctly. I can’t manipulate them at all and none of the controls display. They basically look like empty forms.
Here’s my code for generating prompts using the ticker:
public void ticker(object source, System.Timers.ElapsedEventArgs e)
{
if (groupMissed)
{
incrementsMissed += 1;
if (incrementsMissed > 1)
{
IncrementForm form = (IncrementForm)Application.OpenForms["IncrementForm"];
if (form.InvokeRequired)
{
form.Invoke(new MethodInvoker(delegate { form.Close(); }));
}
}
}
else
{
incrementsMissed = 1;
}
IncrementForm theIncrementForm = new IncrementForm(this, e.SignalTime);
theIncrementForm.Show();
latestIncrement = e.SignalTime;
}
And here’s my code for generating prompts using the “turn prompts off” checkbox:
private void chkbxAlerts_Click(object sender, EventArgs e)
{
if (!chkbxAlerts.Checked)
{
// Ensures that the time missed is covered and restarts the timer
DateTime now;
now = DateTime.Now;
if ((now - latestIncrement).TotalMinutes >= 1) // Only records time if it is equal to or greater than one minute
{
// TO-DO: FIX
if (groupMissed)
{
incrementsMissed += 1;
if (incrementsMissed > 1)
{
IncrementForm form = (IncrementForm)Application.OpenForms["IncrementForm"];
if (form.InvokeRequired)
{
form.Invoke(new MethodInvoker(delegate { form.Close(); }));
}
}
}
else
{
incrementsMissed = 1;
}
IncrementForm theIncrementForm = new IncrementForm(this, now, latestIncrement);
theIncrementForm.Show();
latestIncrement = now;
}
timer.Enabled = true;
}
else
{
// Stops the timer
timer.Enabled = false;
}
}
If you need any further clarification, please let me know. Thanks so much in advance for any help, this has been bugging me.
System.Timers.Timerhas a SynchronizingObject property. If you set that to the main form (or the form that contains the timer), then the timer tick event will be raised on the GUI thread.Do note that
System.Timers.Timerhas the nasty habit of swallowing exceptions that occur in theElapsedevent. If your tick handler throws an exception, you’ll never see it. It’s a nasty bug hider. For that reason, I recommend using eitherSystem.Windows.Forms.TimerorSystem.Threading.Timer. If you use the Windows Forms timer, the elapsed event is raised on the GUI thread. If you useSystem.Threading.Timer, you’ll have to useInvokeas NSGaga shows in his answer.See Swallowing exceptions is hiding bugs for more information about why I discourage the use of
System.Timers.Timer.