在 C# 中使用 DataGridView 和 BindingList 时的线程安全建议
我正在编写一个用于记录事件的类。我的LogClass是作为单例实现的,系统中的任何类都可以写入日志条目。这些条目存储在列表中,当缓冲区填满时,它们会转储到磁盘。
我使用 DataGridView 在执行期间显示 LogClass 的内容,因此我使用 BindingList 以便查看器自动更新。
我想知道我的课程的线程安全性如何。 每当我向列表添加新条目以及迭代列表以将其转储到磁盘时,我都会使用“锁定”。 除了 DataGridView 之外,该类基本上是只写的,因为没有从日志中读取的选项,只能将条目添加到日志中。 转储在内部执行,这是唯一一次在 BindingList 上有显式读取命令。
所以我真正关心的是 DataGridView 和 BindingList 发生了什么? 每次列表更改时,BindingList 都会引发一个事件。 添加新条目时这似乎不是一个问题,因为添加完成时会引发该事件。
我的 Dump() 代码是:
lock (lockObj) {
foreach (LogEntry le in List) {
writeToDisk(le)
removeFromList(le)
}
}
即使我在整个迭代过程中锁定列表,也会向查看器抛出一个事件,表明列表已更改(因为删除),因此由 DataGridView 读取。我真的不想在更改列表时读取/写入任何内容。 有什么想法吗?
I'm writing a class for logging events. My LogClass is implemented as a singleton, and any class in the system can write a log entry. The entries are stored in a List and when a buffer is filled they get dumped to the disk.
I'm using a DataGridView to display the contents of the LogClass during execution, therefore I used the BindingList so that the Viewer would update automatically.
I'm wondering how thread safe my class is.
I'm using "lock" everytime I add a new entry to the list, and when I'm iterating through the list to dump it to the disk.
Besides the DataGridView, the class is basically Write-Only because there isn't an option to read from the log, only to add entrires to the log.
The dump is executed internally, and that is the only time there is a explicit read command on the BindingList.
So my real concern is what goes on with the DataGridView and the BindingList ?
The BindingList throws an event everytime the list changes.
This doesnt seem like a concern when adding new entries, because the event is thrown when the adding finished.
My code for Dump() is:
lock (lockObj) {
foreach (LogEntry le in List) {
writeToDisk(le)
removeFromList(le)
}
}
Even though I'm locking the list during the whole iteration, an event is thrown to the Viewer that the list changed (because of the removal) and therefore being read by the DataGridView. I don't really want anything reading/writing to the list while I'm altering it.
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这并不是真正的问题,因为一旦绑定,您只能通过 Form.Invoke 方法(继承自 Control.Invoke)更改列表。如果您尝试从另一个线程更改列表,.NET 运行时将向您发出异常,并显示“无法从当前线程更改此列表”。
这有一些您可以获取的代码。
问候,
=艾伦
It's not really a concern because, once bound, you can only change the list from the Form.Invoke method (inherited from Control.Invoke). If you try to change the list from another thread, the .NET runtime will bark at your w/ an exception saying something to the effect of "can't change this list from current thread".
This has some code you can grab.
Regards,
=Alan
我认为 BindingList 没有实现更改通知。在这种情况下,我认为这不是线程安全的。
解决方案可能是使用实现 IBindingList 的自定义集合,并更改列表访问器以在返回任何元素之前获取锁定。
我有一个带有更改通知的 IBindingList 自定义实现,因此如果您愿意,我可以分享它。(无论如何,我可能会写一篇关于代码项目的文章来描述该实现..)
I thought that BindingList didn't implement change notification. In this scenario I don't think this is thread safe.
The solution might be to use custom collection that implements IBindingList and change the list accessor to acquire lock before returning any element.
I have a custom implementation of IBindingList with change notification so if you want I can share this.(I'll probably write an article on code project describing the implementation anyway..)