如何用List实现TaskArray方法的数组操作逻辑?未知任务数量场景
Fixing TaskArray with List for Dynamic Task Count
First, let's spot the critical issues in your original code that need addressing before we adapt it to use List<Task>:
- Your
taskArrayis initialized with size 10, but you're looping up to 99 (i < 100) — this will throw anIndexOutOfRangeExceptionimmediately. - The lambda in
Task.Factory.StartNewcaptures the loop variableidirectly, which means all tasks will end up using the final value ofi(100) instead of the iteration-specific value. This is a common closure pitfall. - A fixed-size array can't handle an unknown number of tasks, which is your core requirement.
Here's the revised implementation using List<Task> that solves all these problems, while avoiding pre-filling the list before starting tasks:
public void TaskArray() { ConcurrentBag<int> cb = new ConcurrentBag<int>(); List<Task> taskList = new List<Task>(); // Dynamic list instead of fixed array for (int i = 0; i < 100; i++) { // Capture the current iteration's i value in a local variable to avoid closure issues int taskId = i; // Start the task and add it directly to the list immediately Task task = Task.Factory.StartNew((Object obj) => { int id = (int)obj; Console.WriteLine("Task #{0} created at {1} on thread #{2}.", id, DateTime.Now.ToString("HH:mm:ss.fff"), Thread.CurrentThread.ManagedThreadId); // Add something to the ConcurrentBag if needed cb.Add(id); }, taskId); // Pass the local taskId as the state object taskList.Add(task); } // Wait for all tasks to complete (optional but recommended) Task.WaitAll(taskList.ToArray()); Console.WriteLine($"All {taskList.Count} tasks completed. ConcurrentBag has {cb.Count} items."); }
Key Improvements Explained:
- Dynamic Task Collection:
List<Task>lets you add tasks as you create them, so you don't need to know the total number upfront. Adding to aList<Task>is amortized O(1) and has negligible overhead, so you won't face the "long fill time" concern you mentioned. - Fixing Closure Capture: By assigning
ito a localtaskIdvariable inside the loop, each task gets the correct iteration value instead of sharing the reference to the loop variable. Alternatively, you could passias the state object (which we did here) to avoid the closure entirely. - Safe Concurrent Access:
ConcurrentBag<int>is still the right choice here since multiple tasks will be modifying it concurrently — no need to change that part. - Waiting for Completion: Using
Task.WaitAllensures your method waits for all tasks to finish before proceeding, which is usually desired when working with batches of tasks.
If you need to handle an unknown number of tasks (not just 100), you can adjust the loop condition to whatever logic determines when to stop creating tasks — the List<Task> will adapt seamlessly.
内容的提问来源于stack exchange,提问作者paparazzo
相关产品推荐
相关产品推荐

