我有一个对象列表(音符),它们在播放时在单独的线程上枚举。我这样做是为了让我可以保持UI线程的响应。
虽然正在播放音符(作为枚举的一部分),但我如何允许将新音符添加到列表中(没有明显的集合修改例外)。
我知道我可以将列表复制到临时列表并枚举,但我实际上希望列表随着用户选择更多而增长(这将在第一个音符播放时发生等)。
psuedo逻辑原样:
onClick()
{
Queue.Add(theClickedNote)
Queue.Play() <-- on another thread
}
Play()
{
if(Playing==true){return ;}
foreach(note theNote in Queue)
{
Note.Play();
Queue.Remove(theNote);
}
}
正如您在上面所看到的,每个Click事件都会向Queue添加一个注释,然后在队列中调用play方法。
队列枚举笔记并在删除笔记之前依次播放每个笔记
我希望我已经解释了我想要做的事情吗?
答案 0 :(得分:4)
这样的东西可以与.Net 4中的ConcurrentQueue<T>
一起使用。
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是线程安全的,因此不需要实现锁定。
答案 1 :(得分:0)
您应该使用真实的队列,而不是使用List 然后你的代码将如下所示:
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();
}
}
这段代码不是线程安全的,所以你应该在队列上添加锁,但这是一般的想法。
答案 2 :(得分:0)
正如mike z所建议的那样,使用.NET 4.0中添加的ConcurrentQueue
与其他并发集合一起,此队列允许您异步添加/删除项目+使用基础集合的快照,使用GetEnumerator方法并使用它进行迭代。
请注意,您仍然可能需要处理不同的情况,例如队列为空,这可以通过BlockingCollection来解决,只要集合为空,take方法就会阻塞线程