【发布时间】:2019-11-10 00:07:49
【问题描述】:
首先,this SO post 没有回答这个问题,因为它描述了简单/基本的对象引用问题。我遇到的问题与多线程异步处理有关,其他帖子没有解决。
我有一个多线程的 .NET winforms 应用程序,我正在这样做:
if ( paramList != null ) {
lock ( paramList ) {
foreach ( DictionaryEntry param in paramList ) {
command.Parameters.AddWithValue(param.Key.ToString(), param.Value);
}
}
}
paramList 是一个OrderedDictionary。
我偶尔会在foreach 行收到此错误:
对象引用未设置为对象的实例。
如您所见,param.Key 为空,param.Value 为空。但这没有任何意义,因为paramList 中没有空值,您可以在此处看到:
在屏幕截图中,您只能看到索引 2,但我也检查了索引 0 和 1,同样的,有效数据,没有空值。
我没有使用多线程应用程序的经验,但由于this SO post 中的响应,我将该块放在了lock() 中。在放入 lock() 之前,我偶尔会收到错误 Collection was modified; enumeration operation may not execute. 放入锁后,该错误消失了,但现在我得到了如上所示的对象引用。
我能做些什么来解决这个问题?
编辑
听取了几位海报的建议,我这样做了:
private static object syncLock = new object();
再往下使用:
lock ( syncLock ) {
if ( paramList != null ) {
foreach ( DictionaryEntry param in paramList ) {
command.Parameters.AddWithValue(param.Key.ToString(), param.Value);
}
}
}
这似乎解决了对象引用错误(谢谢大家),但现在我偶尔得到:
集合已修改;枚举操作可能无法执行。
因为我在尝试这种新方法后遇到了一个完全不同的错误,所以我created a new SO question。我不确定这样做是否正确,因为现在看来这些问题是相关的,而我只是看到同一个核心问题的不同症状。
如果有人有想法,仍在寻找解决方案。
【问题讨论】:
-
尝试锁定不同的对象而不是
paramList参见示例:docs.microsoft.com/en-us/dotnet/csharp/language-reference/… -
通常你想要一个:私有只读对象 myLock = new object(),如果它是你试图保护的类变量。否则使锁为静态。第二:在 AddWithValue 之前测试 null。第三,您需要在访问参数列表的任何地方都使用锁,如果您在此处锁定,但不要锁定在添加或删除某些内容的另一个位置,那么您会收到此错误。
-
我认为您正处于一个痛苦的世界,因为您在对概念没有扎实理解的情况下开始使用多线程。如果您有时间阅读,这是一个很好的资源:@987654328@,作者 Joseph Albahari。
标签: c# multithreading thread-safety