How to manage a changing list when doing an enumeration?

I have a list of objects (musical notes) that are listed in a separate stream when they are played. I do this so that I can respond to the user interface thread.

while a note is playing (as part of an enumeration), how can I allow a new note to be added to the list (without an obvious modified collection exception).

I know that I can copy the list to a temporary list and list it, but I really want the list to grow as the user selects more (and this will happen during the first note, etc.).

psuedo logic as is:

onClick() { Queue.Add(theClickedNote) Queue.Play() <-- on another thread } Play() { if(Playing==true){return ;} foreach(note theNote in Queue) { Note.Play(); Queue.Remove(theNote); } } 

As you can see above, each Click event adds a note to the queue and then calls the play method in the queue.

the queue lists the notes and plays each in turn before deleting the note

I hope I explained what I'm trying to make clear?

+4
source share
3 answers

Something like this can be used with ConcurrentQueue<T> in .Net 4.

 ConcurrentQueue<Note> Queue = new ConcurrentQueue<Note>(); void onClick() { Queue.Enqueue(theClickedNote); // start Play on another thread if necessary } void Play() { if (Playing) return; Note note; while(Queue.TryDequeue(out note)) { note.Play(); } } 

ConcurrentQueue is thread safe, so no lock is required.

+4
source

Instead of using a list, you should use a real queue. Then your code will look like this:

  Queue<Note> queue = new Queue<Note>(); void onClick() { queue.Enqueue(note); } void Play() { if (Playing == true) { return; } while (queue.Peek() != null) { var note = queue.Dequeue(); note.play(); } } 

This code is not thread safe, so you should add locks to the queue, but this is a general idea.

0
source

As suggested by mike z, use the ConcurrentQueue added in .NET 4.0
Along with other parallel collections, this queue allows you to add / remove asynchronosly + elements to work with a snapshot of the base collection using the GetEnumerator method and iterating with it. Please note that you still have to deal with different situations, such as an empty queue, this can be solved using the BlockingCollection , which accept a method that blocks the thread while the collection is empty

0
source

Source: https://habr.com/ru/post/1415846/


All Articles