线程与委托存在什么问题?代码抛出System.ArgumentOutOfRangeException异常
First, let's clean up the code snippet you shared (looks like the third connection string was cut off mid-way, so I'll note that):
ArrayList conarr = new ArrayList(); conarr.Add("User ID=sysdba;Password=wrongpass1;" + "Database=C:\\prod\\file.fdb;DataSource=192.168.0.5;Charset=NONE; Connection Timeout=30;Pooling=false;"); conarr.Add("User ID=sysdba;Password=wrongpass2;" + "Database=C:\\prod\\file.fdb;DataSource=192.168.0.5;Charset=NONE; Connection Timeout=30;Pooling=false;"); conarr.Add("User ID=sysdba;Password=GOODPAS..."); // This string is unclosed—probably a copy-paste truncation, but worth checking in your actual code
Since you mentioned this ties into threads and delegates, here are the most likely culprits behind that System.ArgumentOutOfRangeException:
1. Out-of-Bounds Index Access (Most Common)
This exception almost always pops up when you try to access a collection element with an index that's outside the valid range (i.e., less than 0 or greater than/equal to conarr.Count). If your thread code uses something like conarr[i], double-check how i is calculated:
- Did you accidentally use
<= conarr.Countinstead of< conarr.Countin a loop? - Is
ibeing modified by another thread while your delegate is running?
For example, this mistake would trigger the error instantly:
// Bad loop: i goes up to conarr.Count, which is one past the last valid index for(int i = 0; i <= conarr.Count; i++) { var connStr = conarr[i]; // Delegate/threaded database logic here }
2. Thread Safety Issues with ArrayList
ArrayList is not thread-safe. If multiple threads are modifying the list (adding/removing elements) while another thread is reading from it, you can get inconsistent Count values. For example:
- Thread A starts adding a new element to
conarr - Thread B reads
conarr.Countright before Thread A finishes, uses that number to set its loop bounds - Thread A finishes adding, so
conarr.Countis now higher—but Thread B's loop might try to access an index that didn't exist when it started, or vice versa.
Fix this by either using a thread-safe collection like ConcurrentBag (from System.Collections.Concurrent) or wrapping all access/modifications to conarr in a lock block:
lock(conarr) { // Add elements or access indices here }
3. Closure Capture Bug in Delegates
If you're using delegates inside a loop (like with ThreadPool.QueueUserWorkItem or Task.Run), you might be falling victim to a common closure gotcha. When you capture a loop variable directly in a delegate, the delegate holds a reference to the variable—not its value at the time the delegate was created.
Here's the problematic code:
// Bad: The delegate captures a reference to i, not its current value for(int i = 0; i < conarr.Count; i++) { ThreadPool.QueueUserWorkItem(state => { var connStr = conarr[i]; // By the time the thread runs, i might be conarr.Count // Database logic here }); }
By the time the thread executes, the loop has already finished, so i equals conarr.Count—hence the index out of range. Fix this by creating a temporary variable inside the loop to capture the current index value:
// Good: Capture a copy of i in tempIndex for(int i = 0; i < conarr.Count; i++) { int tempIndex = i; ThreadPool.QueueUserWorkItem(state => { var connStr = conarr[tempIndex]; // Database logic here }); }
4. Unclosed String (Syntax Error)
The third connection string in your snippet is unclosed ("User ID=sysdba;Password=GOODPAS..."). If this is how your actual code looks, it would cause a compile error before even hitting the runtime exception. Make sure all string literals are properly closed with a quote.
Quick Fix Checklist
- Verify all index accesses to
conarrstay within0toconarr.Count - 1 - Switch to a thread-safe collection or add locks if multiple threads touch the list
- Fix closure capture issues by using temporary variables in loops
- Double-check all string syntax for unclosed literals
内容的提问来源于stack exchange,提问作者user2265690

