-2

How do I make this dispatch timer 1 line of code instead of this

       private DispatcherTimer timer1;

       public void InitTimer()
        {
            timer1 = new System.Windows.Threading.DispatcherTimer();
            timer1.Tick += new EventHandler(timer1_Tick);
            timer1.Interval = TimeSpan.FromMilliseconds(2000);
            timer1.Start();
        }

the x problem? it gets a null error when I uncheck it to disable it

       private DispatchTimer timer1; //<- Main part of the problem?

        public void InitTimer()
        {
            timer1 = new System.Windows.Threading.DispatcherTimer();
            timer1.Tick += new EventHandler(timer1_Tick);
            timer1.Interval = TimeSpan.FromMilliseconds(2000); 
            timer1.IsEnabled = true;
        }

       private void timer1_Tick(object sender, EventArgs e)
        {

            if (AS.Vis.Visibility != Visibility.Visible == false)
            {
                AS.Vis.Visibility = Visibility.Hidden;
                timer1.IsEnabled = false;
            }
            else
            {
                AS.Vis.Visibility = Visibility.Visible;

                Comp();


            }
        }

        private void AKS_Checked(object sender, RoutedEventArgs e)
        {
            InitTimer();
        AS.Vis.Visibility = Visibility.Visible;
            timer1.IsEnabled = true;// <-Also part of the problem

        }

        private void AKS_Unchecked(object sender, RoutedEventArgs e)
        {
            AS.Vis.Visibility = Visibility.Hidden;

            timer1.IsEnabled = false; //<-The problem
        }

I have tried some "work arounds" that I thought would end up working but they didn't so I came to the conclusion that if the dispatchtimer was one line of code it wouldn't cause a null error since private DispatchTimer timer1; bit of code wouldn't exist but I have been told that isn't really the problem?

BionicCode
  • 1
  • 4
  • 28
  • 44
  • 1
    Use [object initializer](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/object-and-collection-initializers) (also set `IsEnabled = true` instead of calling `Start()`). But for event handler you are [out of luck](https://stackoverflow.com/q/3993601/1997232). – Sinatr May 14 '20 at 07:32
  • 4
    Why would you want to do that? It's perfectly readable as it is. – Markus Deibel May 14 '20 at 07:33
  • Less code =/= better performance. Less is not best. you win nothing by making it shorter. If the code annoy you simply collapse the region of code so that it appears under a plus sign (+). – Drag and Drop May 14 '20 at 07:41
  • @DragandDrop It doesn't annoy me I just get a null reference when I try to disable to timer because of `private DispatchTimer timer1;` not being set to an object so if it was 1 line of code I wouldn't have to use InitTimer and it would allow me to delete the null causer aka fixing my problem. – Navi Packton May 14 '20 at 07:49
  • 3
    Ah - the good old XY Problem. https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem Next time, share that context **up front**. – mjwills May 14 '20 at 07:50
  • Use Microsoft's Reactive Extensions for WPF and then you can do this: `Observable.Timer(TimeSpan.FromSeconds(10.0), DispatcherScheduler.Current)`. – Enigmativity May 14 '20 at 08:13
  • Hence my comment. ;) – mjwills May 14 '20 at 08:41
  • It looks you are calling `AKS_Unchecked` before `InitTimer` was called. That's why the `timer1 `field is not initialized when referenced by `AKS_Unchecked`. Either check if `timer1` is `null` before accessing it or initialize the field from the constructor. – BionicCode May 14 '20 at 08:59
  • Also avoid creating a new DispatcherTimer each time InitTimer is called. One instance is enough and cheaper. – BionicCode May 14 '20 at 09:01
  • 1
    Creating a new timer without stopping the recent and without unsubscribing from the Tick event, keeps all the timers running forever and executing callbacks forever. This is what you are currently doing. Every call to AKS_Checked creates a new timer without stopping the running one and without cleaning up event handlers. You have to be more careful. – BionicCode May 14 '20 at 09:07
  • @BionicCode How would I go about doing that? – Navi Packton May 14 '20 at 21:09

2 Answers2

0

If this is the real problem:

I just get a null reference when I try to disable the timer

Then try this, so the timer variable is initialised earlier.

   private DispatchTimer timer1 = new System.Windows.Threading.DispatcherTimer();

   public void InitTimer()
    {
        timer1.Tick += new EventHandler(timer1_Tick);
        timer1.Interval = TimeSpan.FromMilliseconds(2000);
        timer1.Start();
    }

This will initialise the variable when the class is created, before InitTimer (or your disable function) can be called.

Robin Bennett
  • 3,192
  • 1
  • 8
  • 18
  • 2
    I would argue this answer is premature - until we see the code that isn't working. I mean, you are almost certainly right - but if that is a case there are thousands of applicable duplicates. – mjwills May 14 '20 at 08:00
  • 2
    Keep in mind that this would cause multiple event handlers being attached to the Tick event as InitTimer is potentially called multiple times in his current implementation. Event subscription and field initialisation should be moved to the constructor to ensure it only executes once. – BionicCode May 14 '20 at 09:11
  • @BionicCode - good point, I totally agree. Feel free to edit the answer if you think it'll help. – Robin Bennett May 14 '20 at 15:03
0

Creating a new DispatcherTimer instance without stopping the recent and without unsubscribing from the DispatcherTimer.Tick event, keeps all the timers running forever and executing callbacks forever. This is what you are currently doing. Every call to AKS_Checked creates a new DispatcherTimer without stopping the running one and without cleaning up event handlers.

The following example is a refactored version of your code and guarantees that there will be only one single timer instance.
It also fixes the null-reference issue by initializing the private timer property properly.

DispatcherTimer.Start resets the timer and starts it.

partial class MainWindow : Window
{
  private DispatcherTimer Timer { get; set; }

  public void MainWindow()
  {
    InitializeComponent();
    InitTimer();
  }

  private void InitTimer()
  {
    this.Timer = new System.Windows.Threading.DispatcherTimer();
    this.Timer.Tick += OnTick;
    this.Timer.Interval = TimeSpan.FromMilliseconds(2000); 
  }

  private void OnTick(object sender, EventArgs e)
  {
    if (AS.Vis.Visibility == Visibility.Visible)
    {
      AS.Vis.Visibility = Visibility.Hidden;
      this.Timer.Stop();
    }
    else
    {
      AS.Vis.Visibility = Visibility.Visible;
      Comp();
    }
  }

  private void AKS_Checked(object sender, RoutedEventArgs e)
  {
    AS.Vis.Visibility = Visibility.Visible;

    // Reset and start the timer
    this.Timer.Start();
  }

  private void AKS_Unchecked(object sender, RoutedEventArgs e)
  {
    AS.Vis.Visibility = Visibility.Hidden;
    this.Timer.Stop();
  }
}
BionicCode
  • 1
  • 4
  • 28
  • 44