C# 如何在链表上使用静态计时器?

C# 如何在链表上使用静态计时器?,c#,timer,linked-list,thread-safety,C#,Timer,Linked List,Thread Safety,我正在创建一个包含时间的对象的链接列表。链表按时间排序,这意味着最早的项目将是第一个。我在班上拿着链表,我有一个计时器,它应该总是在链表的第一项上运行。当计时器事件完成时,第一项被移除,计时器以新的第一项时间设置的间隔重新启动。如果插入时间早于第一个项目的项目,也会发生同样的情况。错误:当我用列表中的2个项目运行程序时,经过的事件发生了3次,因此我得到了这个错误 System.NullReferenceException:“对象引用未设置为对象的实例。” System.Collections.G

我正在创建一个包含时间的对象的链接列表。链表按时间排序,这意味着最早的项目将是第一个。我在班上拿着链表,我有一个计时器,它应该总是在链表的第一项上运行。当计时器事件完成时,第一项被移除,计时器以新的第一项时间设置的间隔重新启动。如果插入时间早于第一个项目的项目,也会发生同样的情况。错误:当我用列表中的2个项目运行程序时,经过的事件发生了3次,因此我得到了这个错误

System.NullReferenceException:“对象引用未设置为对象的实例。”

System.Collections.Generic.LinkedList.First.get返回null

因为第一项已被删除,事件将尝试打印其id。 我的问题是为什么第三个事件发生在第一位,因为如果列表中没有项目,计时器不应该被激活 . 这是项目类:

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;
    }
}
公共类TimerItem:i可比较
{
公共int Id{get;}
私有只读日期时间结果时间;
公共TimerItem(int-id,DateTime-resultTime)
{
Id=Id;
结果时间=结果时间;
}
公共双毫秒搜索完成
{
得到
{
if(ResultTime.Subtract(DateTime.Now).Seconds>0)
{
返回ResultTime.Subtract(DateTime.Now).total毫秒;
}
返回1;
}
}
公共整数比较(TimerItem其他)
{
if(ResultTime<其他.ResultTime)
{
返回-1;
}
if(ResultTime==other.ResultTime)
{
返回0;
}
其他的
返回1;
}
}
这是保存链接列表的类:

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();
    }
}
公共静态类TimerManager
{
私有静态LinkedList TimerItems=新LinkedList();
专用静态计时器_Timer=new Timer();
公共静态无效添加(TimerItem TimerItem)
{
如果(TimerItems.First==null | | TimerItems.First.Value.CompareTo(timerItem)>0)
{
TimerItems.AddFirst(timerItem);
SetTimerToFirst();
}
其他的
{
var temp=第一个时间点;
而(temp.Next!=null&&temp.Next.Value.CompareTo(timerItem)只需添加:

_timer.Elapsed -= Completed;

对于已完成的方法,解决了@Dmitry可能重复的问题。

空引用用于第三个事件将第一个项目设置为空,其中程序尝试打印列表中第一个项目的id,该项目已在第二个事件中被删除。我的问题是,为什么第三个事件发生在第一个位置,因为如果列表中没有任何项,则不应激活imer。net提供的3个计时器类中,您使用的是哪一个?@ScottChamberlain using System.Timer尽管看起来有些刺耳,但建议的副本会告诉您如何解决此问题:在调试器中逐步检查代码,您将看到哪里出了问题。