【问题标题】:System.Timers.Timer throwing an ExceptionSystem.Timers.Timer 抛出异常
【发布时间】:2018-01-29 02:24:33
【问题描述】:

我正在使用 List 实现代码。每个列表都有一个类类型项。此类的成员之一是名为“TimeOut”的 System.Timer.Timer 变量。 TimeOut.Interval 的值为 10,TimeOut.Elapsed 事件应该在每个 TimeOut.Interval(即 10)触发一次。

事件是从列表中删除该项目。事件被重载使得

TimeOut.Elapsed += (sender, e) => DeleteEntry(sender, e, i)

其中 i 是列表中项目的索引。

对于事件方法,

public void DeleteEntry(object sender, System.Timers.ElapsedEventArgs e, int i)
{
    //Delete Item from List
    listTable.RemoveAt(i);
}

我的问题是,如果两个项目一起启动它们的计时器并决定在相同的指定间隔后调用 EventHandler,则首先添加到列表中的一个被删除,然后当第二个被立即调用时,它会抛出一个错误告诉我索引超出范围。发生这种情况是因为其中一个项目被删除,列表向上移动了它的索引,并且发送到 DeleteEntry 方法的“i”是不再存在的旧项目。

在其他情况下,当列表中有两个以上的项目时,它会删除错误的项目,因为该方法使用了错误的索引。

使用数组不是我的选择。每次删除元素时都需要对数组进行碎片整理。

我该如何解决这个问题?我是否需要对 ThreadPool 做一些事情,设置一个标志或类似的东西? SynchronizingObject 属性有帮助吗?

谢谢。

【问题讨论】:

  • 您应该找到除索引以外的方法来识别您的列表项,或者 - 您的多个计时器事件应该只收集索引并且唯一的一个专用计时器事件应该删除它们(但这涉及更多同步开销)

标签: c# timer threadpool eventhandler


【解决方案1】:

解决方案:

根据您的说法,您的问题似乎是列表移动,您不知道该项目在什么时候。如果是这种情况,您将需要访问列表的 Count 属性,该属性会告诉您列表中的项目数量。小心使用它,因为它不考虑 0 的索引。

解决方案:

根据您的说法,您的问题似乎是列表移动,您不知道该项目在什么时候。如果是这种情况,您将需要访问列表的 Count 属性,该属性会告诉您列表中的项目数量。小心使用它,因为它不考虑 0 的索引。

编辑:

例子:

    private static List<int> Numbers = new List<int>();
    private static readonly object NumbersLock = new object();
    static void Main(string[] args)
    {
        Thread X = new Thread(() => {
            AddNumbers();
        });

        Thread Y = new Thread(() => {
            AddNumbers();
        });

        X.Start();
        Y.Start();
    }

    private static void AddNumbers() {
        Random r = new Random(DateTime.UtcNow.Millisecond);

        while (true) {
            lock (NumbersLock) {
                Numbers.Add(r.Next(0, 100));
            }
        }
    }

【讨论】:

  • 取决于 Count 属性并不总是准确的。它可能适用于一两个项目,但列表中有许多项目进出,我不能依赖。
  • @MohammedNafie 我认为它可以被认为是非常可靠的,如果你仍然有疑问,你可以创建一个锁来一次只用一个线程访问它。了解更多信息here
  • 感谢您的回复。使用锁很有趣。我没有提到这个列表上有一个使用 WaitOne() 和 ReleaseMutex() 的互斥锁。错误仍然发生。请问Lock和Mutex的区别?
  • @MohammedNafie 简而言之,锁限制对象一次只能被系统的一个部分访问,但互斥体可以被多个访问。更多信息here。另外,如果我的解决方案有效,请记得标记它,因为它可以帮助我成长,其他有类似问题的人也可以找到此回复。
  • 我认为 lock 并没有解决我的问题。我对从 TheadPool 运行的 EventElapsed 和我创建的线程上的 Lock 都应用了锁。问题仍然存在。就像 Henk Holterman 的示例 here 一样
猜你喜欢
  • 2013-05-24
  • 2011-05-30
  • 1970-01-01
  • 2011-02-25
  • 2012-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多