2017-02-01 4 views
1

У меня есть следующий код:WPF Таймер + витрины заладились

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();   
    } 
} 

я открываю окно со следующим:

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; 
     } 

Это приложение проверить некоторые веб-сайты, и если информация изменилась она даст я предупреждаю, у него есть 3 окна с предупреждением, и у меня возникла эта проблема:

Открываю 3 окна, и я хочу, чтобы они напомнили мне о предупреждении в течение 2, 4, 6 минут, никаких проблем, пока здесь , они будут скрываться и будут отображаться на экране в то время. Но если я попытаюсь изменить напоминание снова, это создаст еще один таймер или что-то вроде этого, я не совсем понимаю поведение.

Также период, в который будет отображаться окно, будет намного короче, чем введенное время. https://i.stack.imgur.com/gkeu6.png Если я нажимаю ОК окно следует закрыть, и они делает, но таймер каким-то образом еще жива и будет пытаться показать окно, которое я закрыл так он будет генерировать эту ошибку https://i.stack.imgur.com/4dDzJ.png

Хорошо я думаю, что всякий раз, когда я ударил напомнить, что он создаст новый таймер, а старый будет работать (но это не объясняет, почему иногда все окна будут всплывать сразу, даже если напоминание не совпадает), и это правильно:

Что я могу сделать, чтобы избавиться от старого таймера и позволить только новому.

Также, если вы можете дать мне какие-либо предложения о том, как я должен улучшить свой код, который я слушаю.

ответ

1

Если я нажимаю ОК окно должно закрыться и они делает, но таймер каким-то образом еще жива и будет пытаться показать окно, которое я закрыл так он будет генерировать эту ошибку

Отказаться dispatcherTimer_Tick и остановить таймер перед закрытием окна

private void btnOK_Click(object sender, RoutedEventArgs e) 
{ 
    if (dispatcherTimer != null) 
    { 
     dispatcherTimer.Tick -= dispatcherTimer_Tick; 
     dispatcherTimer.Stop(); 
    } 
    Window.GetWindow(this).Close(); 
} 

если я пытаюсь изменить напоминание снова создаст другой таймер

То же самое, когда вы начинаете новый таймер

public void InitTimer() 
{ 
    if (dispatcherTimer != null) 
    { 
     dispatcherTimer.Tick -= dispatcherTimer_Tick; 
     dispatcherTimer.Stop(); 
    } 
+0

Я пробовал это, и он работал, я также изменяю dispatcherTIme от статического до нестатического – Spoukey

0

Хорошо я думаю, что всякий раз, когда я нажал на кнопку напомнит это создаст новый таймер и старый один будет по-прежнему работать

Да, конечно, каждый раз, когда вы звоните InitTimer() вы создаете новый таймер. Но и вы не убили старого, и он не будет собирать мусор, потому что у него есть подписка на события. Таким образом, каждый раз он создает новый таймер, и все они гасятся всякий раз, когда должны.

Чтобы избежать этого, вы должны быть осторожны с подпиской в ​​целом. Всякий раз, когда вы пишете что-то вроде:

dispatcherTimer.Tick += dispatcherTimer_Tick; 

Вы должны написать также где-то (как правило, в объекте очистки):

dispatcherTimer.Tick -= dispatcherTimer_Tick; 

В противном случае событие будет еще жить. Это очень распространенная ошибка в C#, ответственная за множество утечек памяти.

Быстрый обходной путь для вас может быть:

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(); 
} 

Кроме того, если вы можете дать мне какие-либо предложения о том, как я должен улучшить свой код, который я слушаю

Чтобы быть честным , этот код довольно плохой, не проверяемый и с плохими именами.Чтобы улучшить ваше ремесло, я могу предложить вам узнать о MVVM pattern и прочитать Clean Code.

Надеюсь, это поможет.

+0

Я попытался это, но кажется, что это Бесполезный 't работа такое же поведение, как и раньше, – Spoukey

+0

уверен, что вам обязательно нужно остановить старый таймер, а также – Ouarzy

0

Что я могу сделать, чтобы избавиться от старого таймера и позволить только новому?

Попытка остановить старый таймер, прежде чем начать новую:

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(); 
} 
Смежные вопросы