C# 如何在执行枚举时管理更改列表?
我有一个对象(音符)列表,当它们播放时,在单独的线程上枚举。我这样做是为了让UI线程保持响应性 当一个音符播放时(作为枚举的一部分),我如何允许将一个新音符添加到列表中(没有明显的集合修改异常) 我知道我可以将列表复制到一个临时列表中并列举出来,但我实际上希望随着用户选择更多的列表而增长(这将在播放第一个音符时发生) psuedo逻辑原样:C# 如何在执行枚举时管理更改列表?,c#,multithreading,list,enumeration,C#,Multithreading,List,Enumeration,我有一个对象(音符)列表,当它们播放时,在单独的线程上枚举。我这样做是为了让UI线程保持响应性 当一个音符播放时(作为枚举的一部分),我如何允许将一个新音符添加到列表中(没有明显的集合修改异常) 我知道我可以将列表复制到一个临时列表中并列举出来,但我实际上希望随着用户选择更多的列表而增长(这将在播放第一个音符时发生) psuedo逻辑原样: onClick() { Queue.Add(theClickedNote) Queue.Play() <-- on another thread
onClick()
{
Queue.Add(theClickedNote)
Queue.Play() <-- on another thread
}
Play()
{
if(Playing==true){return ;}
foreach(note theNote in Queue)
{
Note.Play();
Queue.Remove(theNote);
}
}
onClick()
{
添加(单击注释)
Queue.Play()您应该使用真实的队列,而不是使用列表
那么您的代码将如下所示:
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();
}
}
Queue Queue=new Queue();
void onClick()
{
排队。排队(注);
}
无效播放()
{
如果(Playing==true){return;}
while(queue.Peek()!=null)
{
var note=queue.Dequeue();
注:play();
}
}
此代码不是线程安全的,因此您应该在队列上添加锁,但这是一般的想法。类似的内容可以与.Net 4中的ConcurrentQueue一起使用
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=new ConcurrentQueue();
void onClick()
{
Queue.Enqueue(点击注释);
//如有必要,在另一个线程上开始播放
}
无效播放()
{
如果(玩)回来;
注释;
while(Queue.TryDequeue(out note))
{
注:Play();
}
}
ConcurrentQueue是线程安全的,因此不需要实现锁定。正如mike z所建议的,使用.NET 4.0中添加的
与其他并发集合一起,此队列允许您通过使用GetEnumerator方法并对其进行迭代,异步添加/删除项并使用底层集合的快照。
请注意,您可能仍然需要处理不同的情况,例如队列为空,这可以通过解决,只要集合为空,take方法将阻止线程队列是列表
还是队列
?看起来像列表
,但您的变量名称很混乱,并且只显示伪代码。…对不起,有很多代码,因此psuedo,队列是一个列表…我敢问什么是队列,而不用谷歌你要找的是生产者和消费者
模式…@DanielGwalter不枚举队列。只需依次将每个项目出列。如果可以使用.Net 4,请查看ConcurrentQueue。@Mikez with ConcurrentQueue我可以在枚举时添加到它吗?Peek
如果队列为空,则抛出。您应该检查计数。这完成了任务,如果您有时间,您可以在上面的示例中向我展示一下锁的情况吗…(锁对我来说是新的)mike z使用ConcurrentQueue有更好的解决方案,因为它是线程安全的。如果您想给我的解决方案添加锁,只需在queue.enqueue和queue.dequeue方法调用周围加一个锁(queue)块。它看起来类似于锁(queue){queue.enqueue(note);}