Reputation: 15
I have the following code :
public partial class FereastraAlerta : UserControl
{
private static DispatcherTimer dispatcherTimer;
public FereastraAlerta()
{
InitializeComponent();
}
public void InitTimer()
{
dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, Convert.ToInt32(textBox.Text), 0);
dispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
CommandManager.InvalidateRequerySuggested();
Window.GetWindow(this).Show();
}
private void textBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key < Key.D0 || e.Key > Key.D9)
{
e.Handled = true;
}
}
private void btnOK_Click(object sender, RoutedEventArgs e)
{
Window.GetWindow(this).Close();
}
private void btnRemind_Click(object sender, RoutedEventArgs e)
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if(Window.GetWindow(this).Title == "ANM")
config.AppSettings.Settings["nIntervalDeTimpReminderANM"].Value = textBox.Text;
else if (Window.GetWindow(this).Title == "CAS")
config.AppSettings.Settings["nIntervalDeTimpReminderCAS"].Value = textBox.Text;
else if (Window.GetWindow(this).Title == "MS")
config.AppSettings.Settings["nIntervalDeTimpReminderMS"].Value = textBox.Text;
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
Window.GetWindow(this).Hide();
InitTimer();
}
}
I open this window with the following :
if (data != strDataCurentaANM)
{
FereastraAlerta win1 = new FereastraAlerta();
Window window1 = new Window
{
Title = "ANM",
Content = win1,
Height = 300,
Width = 300
};
window1.Show();
win1.label.Content = textAvertizare + " " + data;
win1.textBox.Text = ConfigurationManager.AppSettings["nIntervalDeTimpReminderANM"];
strDataCurentaANM = data;
modifica = true;
}
This application check some websites and if the information changed it give me a warning, it have 3 warning windows at the moment and I got this problem:
I open 3 windows and I want them to remind me about the warning in 2 , 4 ,6 min, no problem until here, they will hide and will apear on the screen in that time. But if I try to modify the reminder again it will create another timer or something like this , I don't really understand the behavior.
Also the period that the window will apear it will be much shorter that the time inserted .https://i.sstatic.net/gkeu6.png If I press ok the window should close and they does but the timer is somehow still alive and will try to show the window which I closed so it will generate this error https://i.sstatic.net/4dDzJ.png
Ok my guess is that whenever I hit the remind button it will create a new timer and the old one will still run(but this don't explain why sometimes all the windows will popup at once even if the reminder is not the same) and this is right:
What can I do in order to get rid of the old timer and let only the new one.
Also if you can give me any suggestions about how I should improve my code I'm listening .
Upvotes: 1
Views: 97
Reputation:
If I press ok the window should close and they does but the timer is somehow still alive and will try to show the window which I closed so it will generate this error
Unsubscribe the dispatcherTimer_Tick
and stop the timer before closing your window
private void btnOK_Click(object sender, RoutedEventArgs e)
{
if (dispatcherTimer != null)
{
dispatcherTimer.Tick -= dispatcherTimer_Tick;
dispatcherTimer.Stop();
}
Window.GetWindow(this).Close();
}
if I try to modify the reminder again it will create another timer
Same thing when you start a new timer
public void InitTimer()
{
if (dispatcherTimer != null)
{
dispatcherTimer.Tick -= dispatcherTimer_Tick;
dispatcherTimer.Stop();
}
Upvotes: 1
Reputation: 169200
What can I do in order to get rid of the old timer and let only the new one?
Try to stop the old timer before you start a new one:
private void btnRemind_Click(object sender, RoutedEventArgs e)
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (Window.GetWindow(this).Title == "ANM")
config.AppSettings.Settings["nIntervalDeTimpReminderANM"].Value = textBox.Text;
else if (Window.GetWindow(this).Title == "CAS")
config.AppSettings.Settings["nIntervalDeTimpReminderCAS"].Value = textBox.Text;
else if (Window.GetWindow(this).Title == "MS")
config.AppSettings.Settings["nIntervalDeTimpReminderMS"].Value = textBox.Text;
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
Window.GetWindow(this).Hide();
//STOP the old timer here:
if (dispatcherTimer != null)
{
dispatcherTimer.Stop();
}
InitTimer();
}
Upvotes: 0
Reputation: 3043
Ok my guess is that whenever I hit the remind button it will create a new timer and the old one will still run
Yes, definitely, each time you call InitTimer() you create a new timer. But also you didn't kill the old one, and it wont be garbage collected because it has an event subscription. Thus each time it creates a new timer and they all tick whenever they should.
To avoid that, you have to be carefull with subscription in general. Whenever you write something like:
dispatcherTimer.Tick += dispatcherTimer_Tick;
You have to write also somewhere (usually in object cleanup):
dispatcherTimer.Tick -= dispatcherTimer_Tick;
Otherwise the event will still live. It is a really common error in C#, responsible for lots of memory leaks.
A quick workaround for you could be:
public void InitTimer()
{
if (dispatcherTimer != null)
{
dispatcherTimer.Tick -= dispatcherTimer_Tick;
}
dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Tick += dispatcherTimer_Tick;
dispatcherTimer.Interval = new TimeSpan(0, Convert.ToInt32(textBox.Text), 0);
dispatcherTimer.Start();
}
Also if you can give me any suggestions about how I should improve my code I'm listening
To be honest, this code is pretty bad, not testable and with bad names. To improve you craft I can suggest you to learn about the MVVM pattern and to read Clean Code.
Hope it helps.
Upvotes: 0