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

时间:2018-05-31 19:07:46

标签: c# timer linked-list thread-safety

我正在创建一个持有时间的对象的链接列表。链接列表按时间排序,这意味着最早的项目将是第一个。在持有链表的类中,我保留一个计时器,该计时器应始终在列表中的第一项上运行。当计时器的事件结束时,第一项被移除,计时器以新的第一项的时间设置的间隔重新启动。如果插入的时间早于第一个项目,则会发生同样的情况。错误:当我在列表中运行带有2个项目的程序时,Elapsed事件发生了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;
    }
}

这是持有链表的类:

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

1 个答案:

答案 0 :(得分:0)

只需添加:

NodeList.item(i).focus

到Completed方法解决了问题