-2

I am implementing a code using List<>. Each list has an Class Type item. One of the members of this class is a System.Timer.Timer variable called "TimeOut". The TimeOut.Interval value is 10 and TimeOut.Elapsed Event should be triggered every TimeOut.Interval (which is 10).

The Event is to delete that item from the list. The Event is overloaded such that

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

where i is the index of the item in the list.

For the Event method,

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

My problem is if two items started their timer together and decided to call the EventHandler after the same specified interval, the one added to the list first is deleted, and then when the second one is called immediately., it throws an error telling me that the index is out of bounds. This happens because one of the items is deleted, the lists shifted its index up and and the "i" sent to the DeleteEntry Method is the old one which is no longer existent.

In other cases when I have more than two items in the list, it deletes the wrong one since the method uses a wrong index.

Using Arrays is not an option for me. Too much work to de-fragment the array every deletion of an element.

How can I solve this? Do I need to do something with the ThreadPool, setting a flag or something like that? Can SynchronizingObject property help in anyway?

Thank you.

Mohammed Nafie
  • 151
  • 1
  • 10
  • you should either to find the method other than index to identify your list items, or - your multiple timer events should only collect indexes and the the only one dedicated timer event should delete them (but this involves more synchronization overhead) – Roman Ananyev Aug 21 '17 at 05:36

1 Answers1

0

Solution:

From what your saying it seems that your problem is the list shifting and you don't know at what point the item is. If that is the case you will want to access the Count property of the list which tells you the amount of items in the list. Be careful working with it as it is does not account for the indexing of 0.

Solution:

From what your saying it seems that your problem is the list shifting and you don't know at what point the item is. If that is the case you will want to access the Count property of the list which tells you the amount of items in the list. Be careful working with it as it is does not account for the indexing of 0.

Edit:

Example:

    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));
            }
        }
    }
Sean Mitchell
  • 447
  • 2
  • 21
  • Depending on the Count property will not always be accurate. it may work with one or two items, but with many items in and out of the list, I cannot depend that. – Mohammed Nafie Aug 21 '17 at 05:52
  • @MohammedNafie I think it could be considered very reliable and if you still had doubts you could create a lock to access it with only one thread at a time. Learn more about it [here](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement). – Sean Mitchell Aug 21 '17 at 06:04
  • Thanks for your reply. Using lock is interesting. I haven't mentioned that There is a Mutex lock using WaitOne() and ReleaseMutex() on this List. The error still occurs. May I know the difference between Lock and Mutex? – Mohammed Nafie Aug 21 '17 at 06:12
  • @MohammedNafie In a nutshell a lock limits the object to be accessed by only one part of the system at once, but a mutex can be accessed by more than one. More information [here](https://stackoverflow.com/questions/2332765/lock-mutex-semaphore-whats-the-difference). Also if my solution works please remember to mark it as it helps me grow and others with similar issues find this response. – Sean Mitchell Aug 21 '17 at 06:17
  • I think lock has not solved my problem. I applied the lock on both the EventElapsed that runs from the TheadPool and the Lock on my created threads. The problem still occurs. Like the example [here](https://stackoverflow.com/questions/18345042/using-lock-statement-with-threadpool-in-c-sharp) by Henk Holterman – Mohammed Nafie Aug 21 '17 at 06:49
  • @MohammedNafie Instead of locking those items create a private, read only, object and then initialize it. Like ListLock, then lock ListLock and access the list. – Sean Mitchell Aug 21 '17 at 12:18
  • I am still trying to make it work correctly. The problem seems that the Timer ThreadPool Thread does not want see the lock. I have tried that on normally created threads and it works. But when it comes to creating Timers from different Threads running in the Threadpool, they don't see the lock! – Mohammed Nafie Aug 22 '17 at 06:32
  • Please look at my edit again. I will post a example, it is almost impossible for this not to be working. Also make sure your lock is not a local to the thread but a global variable accessible by all threads. – Sean Mitchell Aug 22 '17 at 12:15
  • I'll post it in about 30 minutes. – Sean Mitchell Aug 22 '17 at 12:17
  • The only issue with my example is that you'll run out of memory due to its behavior. @MohammedNafie – Sean Mitchell Aug 22 '17 at 12:42
  • Mitchel, Thanks a lot for following up with my issue. I will implement your example and see how this is behaving. I will comment with the results when I reach them. – Mohammed Nafie Aug 22 '17 at 23:25
  • @MohammedNafie No problem anything to help, let me know if it works, and if does please mark my question. – Sean Mitchell Aug 23 '17 at 02:54