-
-
Notifications
You must be signed in to change notification settings - Fork 74
Description
When I reuse a connection between two commands on two different threads (not in parallel), I might run into a race condition. See example:
Using command1 with connection1:
FbCommand command1 = ...
void f() {
command1.Connection = connection1;
command1.ExecuteNonQuery();
// command1.Connection = null;
}
Then, after f has finished:
void g() {
command1.Connection = connection2;
command1.ExecuteNonQuery();
}
Meanwhile in a different thread (after f has finished as well):
FbCommand command2 = ...
void h() {
command2.Connection = connection1;
command2.ExecuteNonQuery();
}
command1.Connection = connection2
releases connection1 from command1 which indirectly invokes connection1.InnerConnection.RemovePreparedCommand()
. However, if g and h are executed at the same time, this can cause both threads to attempts accessing connection1.InnerConnection._preparedCommands
, potentially causing this exception (or something similar):
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.Collections.Generic.HashSet`1.Enumerator.MoveNext()
at FirebirdSql.Data.FirebirdClient.FbConnectionInternal.TransactionCompleted()
at FirebirdSql.Data.FirebirdClient.FbTransaction.CompleteTransaction()
at FirebirdSql.Data.FirebirdClient.FbTransaction.Commit()
at FirebirdSql.Data.FirebirdClient.FbCommand.CommitImplicitTransaction()
at FirebirdSql.Data.FirebirdClient.FbCommand.ExecuteNonQuery()
My current workarounds are:
- Set
command1.Connection = null
immediately when the connection is no longer used by command1 (the commented out line in f) - Avoid reusing the connection altogether.
Is this an actual issue? am I using this wrong? Should I avoid reusing the same connection between thread/commands altogether, or simply setting Connecton=null should be enough?
Thanks!