0

I'm creating a linked list of objects holding a time. the linked list is sorted by that time, which mean that the most early item would be first. with in the class holding the linked list i keep a timer that should operate always on the first item in the list. when the event of the timer is done, the first item is removed, and the timer restart with the interval set by the new first item's time. the same happened if an item with an earlier time than the first item is being inserted. the error: when i run the program with 2 items in the list the Elapsed event occurring 3 times, and therefore i get the error this

System.NullReferenceException: 'Object reference not set to an instance of an object.'

System.Collections.Generic.LinkedList.First.get returned null.

because the first item has been removed and the event try to print it's id. my question is why the third event happened in the first place, since the timer shouldn't be activated if there is no items in the list . this is the item class:

public class TimerItem : IComparable<TimerItem>
{
    public int Id { get; }
    private readonly DateTime ResultTime;

    public TimerItem (int id, DateTime resultTime)
    {
        Id = id;
        ResultTime = resultTime;
    }


    public double MilliSecondsCountToCompletion
    {
        get
        {
            if (ResultTime.Subtract(DateTime.Now).Seconds > 0)
            {
                return ResultTime.Subtract(DateTime.Now).TotalMilliseconds;
            }
            return 1;
        }
    }

    public int CompareTo(TimerItem other)
    {
        if (ResultTime < other.ResultTime)
        {
            return -1;
        }
        if (ResultTime == other.ResultTime)
        {
            return 0;
        }
        else
            return 1;
    }
}

this is the class holding the linked list:

public static class TimersManager
{
    private static LinkedList<TimerItem > TimerItems = new LinkedList<TimerItem>();

    private static Timer _timer = new Timer();

    public static void Add(TimerItem  timerItem )
    {
        if (TimerItems.First == null || TimerItems.First.Value.CompareTo(timerItem ) > 0)
        {
            TimerItems.AddFirst(timerItem);
            SetTimerToFirst();
        }
        else
        {
            var temp = TimerItems.First;
            while (temp.Next != null && temp.Next.Value.CompareTo(timerItem) <= 0)
            {
                temp = temp.Next;
            }
            TimerItems.AddAfter(temp, timerItem);
        }


    }

    private static void Completed(Object sender, EventArgs e)
    {
        _timer.Stop();

        Console.WriteLine(TimerItems.First.Value.Id);
        TimerItems.RemoveFirst();
        if (TimerItems.First != null)
        {
            SetTimerToFirst();
        }

    }

    private static void SetTimerToFirst()
    {
        _timer.Interval = TimerItems.First.Value.MilliSecondsCountToCompletion;
        _timer.AutoReset = false;
        _timer.Elapsed += Completed;
        _timer.Start();
    }
}
Itay Tur
  • 683
  • 1
  • 15
  • 40
  • 2
    Possible duplicate of [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Dmitry May 31 '18 at 19:09
  • 1
    @Dmitry the null reference is for the first item being set to null by the third event, in which the program try to print the id of the first item in the list which have been removed in the second event. my question is why the third event happened in the first place, since the timer shouldn't be activated if there is no items in the list – Itay Tur May 31 '18 at 19:20
  • Which of the 3 Timer classes .net provides are you using? – Scott Chamberlain May 31 '18 at 19:54
  • @ScottChamberlain using System.Timers – Itay Tur May 31 '18 at 19:56
  • Even though it might seem snarky, the proposed duplicate tells you how to solve this: step through your code in the debugger, and you'll see where it's going wrong. – Brian May 31 '18 at 20:02

1 Answers1

0

Simply adding :

_timer.Elapsed -= Completed;

to the Completed method solved the problem

Itay Tur
  • 683
  • 1
  • 15
  • 40