Reputation: 7218
I have the following code in my .NET 4.6.2 winforms app:
paramList is an OrderedDictionary
.
if ( paramList != null ) {
foreach ( DictionaryEntry param in paramList ) {
command.Parameters.AddWithValue(param.Key.ToString(), param.Value);
}
}
It always worked great until I started implementing more async/multithreaded processing in the application. Now, sporadically, I get the following error when the above code runs:
System.InvalidOperationException: 'Collection was modified; enumeration operation may not execute.'
It doesn't seem like I'm modifying the collection at all, so I don't know why it's complaining.
I understand the discussion/solutions in these posts, but it doesn't seem to apply to mine:
Collection was modified exception
System.InvalidOperationException: Collection was modified
What is the best way to make this thread safe?
EDIT #1
I have this now:
private static object syncLock = new object();
[...]
lock ( syncLock ) {
if ( paramList != null ) {
foreach ( DictionaryEntry param in paramList ) {
command.Parameters.AddWithValue(param.Key.ToString(), param.Value);
}
}
}
I ran it a few times and then the problem came back again:
How can this still be happening, even inside a lock()
? What can I do?
EDIT #2
paramList
is always created by the caller and passed into a function, for example:
var paramList = new OrderedDictionary();
paramList.Add("RuleID", btRule.RuleID);
paramList.Add("TypeSeq", 0);
paramList.Add("Type", btRule.Action);
bool result = await ExecuteQueryAsync(sql, paramList, connection);
public static async Task<bool> ExecuteQueryAsync(string sql, OrderedDictionary paramList, SqlConnection connection) {
try {
using ( SqlCommand command = new SqlCommand(sql, connection) ) {
command.CommandType = CommandType.Text;
lock ( syncLock ) {
if ( paramList != null ) {
foreach ( DictionaryEntry param in paramList ) {
command.Parameters.AddWithValue(param.Key.ToString(), param.Value);
}
}
}
command.CommandTimeout = 0;
await command.ExecuteNonQueryAsync();
}
return true;
}
catch ( Exception ex ) {
[...]
}
}
Upvotes: 0
Views: 743
Reputation: 35037
Because of if ( paramList != null ) {
my guess is that paramList
is reused by different actors. You will need to use a different instances per unit of work.
Upvotes: 1