如何在迭代时将 ListItem 添加到列表中(C#)?
我有一个小型应用程序,它使用BackgroundWorker 来处理IEnumerator
。
代码基本上是这样的:
while(true){
foreach(T item in list){
// Process each item and send process
// Add an object in child List ( List<T1> item.Result )
}
Thread.Sleep(500);
}
现在我有一个按钮和一个文本框,它将直接添加到 IEnumerator。
问题是,在我添加按钮后,后台工作人员继续处理当前正在处理的项目,但在完成该项目后将停止。它不会继续。
如何安全地将项目添加到列表中而不影响后台工作人员?除了后台工作人员之外,还可以向项目添加对象。对此应该采取什么解决方案?
谢谢
I have a small application that using BackgroundWorker to process the IEnumerator<T> list
at all time.
The code basically like this:
while(true){
foreach(T item in list){
// Process each item and send process
// Add an object in child List ( List<T1> item.Result )
}
Thread.Sleep(500);
}
Now I have a button and a textbox, which will add directly to the IEnumerator.
The problem is that after I add button, the backgroundworker continue to process it's currently processing Item, but will stop after finish that item. It does not continue.
How can I safely add an Item to the list without affect the backgroundworker? Beside the background worker also do adding objects to the item. What should be the solution for this?
Thank you
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
让后台工作人员迭代原始列表的副本,而不是列表本身。
如果您在枚举集合时尝试修改集合,则枚举器将引发异常。来自文档:
Have the background worker iterate over a copy of the original list, not the list itself.
If you attempt to modify a collection while enumerating over it, the enumerator will throw an exception. From the docs:
您应该首先学习有关多线程编程的基础知识,所以,就这样吧。
尝试一下:
这里的队列比列表更好,因为它允许您添加和删除其中的元素,而不必担心当前元素的索引 - 您只需
Enqueue()
上的项目other 和,以及Dequeue()
它们在另一个上。使用 System.Collections.Concurrent 命名空间中的类,它会自动为您处理线程安全访问(并且,由于您可能想要稍后阅读的复杂原因,它比简单的更快)锁())。
现在,前台线程:
这里最神奇的部分是在
WaitHandle
上调用的Set()
(是的,AutoResetEvent
是一个WaitHandle
)。它唤醒一直在等待同步事件触发的单个线程,而不使用诸如 Thread.Sleep() 之类的丑陋结构。对Sleep()
的调用几乎总是多线程代码中错误的标志!好的,最后一部分 - 工作线程。这里没有太多变化:
You should learn the basics about multi-threaded programming first, so, here it goes.
Try something along this:
The queue is better here than the list, because it allows you to add and remove elements from it without worrying about the index of the current element - you just
Enqueue()
items on the other and, andDequeue()
them on the other. Use a class fromSystem.Collections.Concurrent
namespace, which handles thread-safe access for you automatically (and, due to complicated reasons you might want to read on later, is faster than a simplelock()
).Now, the foreground thread:
The sprinkly-magical part here is the
Set()
invoked on ourWaitHandle
(yes,AutoResetEvent
is an implementation of aWaitHandle
). It wakes up a single thread that has been waiting for the synchronization event to fire, without using such ugly constructs asThread.Sleep()
. A call toSleep()
is almost always a sign of a mistake in multithreaded code!Ok, for the last part - worker thread. Not many changes here:
您可能需要使用“lock”关键字来防止从两个代码位置同时访问共享的“list”变量。
http://msdn.microsoft.com/en-我们/library/c5kehkcz(v=vs.71).aspx
You probably need to use the "lock" keyword to prevent simultaniously accessing the shared "list" variable from both places of code.
http://msdn.microsoft.com/en-us/library/c5kehkcz(v=vs.71).aspx