You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Task.Run()导致调用循环出现意外索引越界问题

问题描述

我有如下C#代码:

public List<bool> scaleActive { get; private set; }
//...
for (int i = 0; i < scaleActive.Count; i++)
{
    if (scaleActive[i])
    {
        //...
        Task.Run(() => NewportUpload.SendBasket(localTempPath,
            string.Format("{0}{1}", basketNamesBuy[i], CSV), tradeBasket,
            privateKeyFileName, privateKeyPassphrase, instinetHost, instinetUserName,
            instinetRemotePath));
        //...
    }
}

运行时出现以下错误:

System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index

调试发现i的值大于scaleActive的Count,这不符合预期。但移除Task.Run()改为同步调用如下代码时则运行正常:

public List<bool> scaleActive { get; private set; }
//...
for (int i = 0; i < scaleActive.Count; i++)
{
    if (scaleActive[i])
    {
        //...
        NewportUpload.SendBasket(localTempPath,
            string.Format("{0}{1}", basketNamesBuy[i], CSV), tradeBasket,
            privateKeyFileName, privateKeyPassphrase, instinetHost, instinetUserName,
            instinetRemotePath);
        //...
    }
}

scaleActive和basketNamesBuy在程序中均未被修改,为何使用Task.Run()时循环会出现索引越界?

问题原因及解决方法

这是C#中闭包捕获循环变量的经典问题:

  • 当你在Task.Run()的lambda表达式中使用变量i时,lambda捕获的是i的引用,而不是当前循环迭代的i的副本。
  • 循环本身是同步执行的,速度远快于后台任务的启动和执行。当后台任务真正开始执行basketNamesBuy[i]或scaleActive[i]时,循环可能已经完成了多次迭代,甚至已经结束,此时i的值已经超过了scaleActive.Count或basketNamesBuy.Count的范围,自然就抛出索引越界异常。
  • 同步调用时,代码是按顺序执行的,每次调用SendBasket时i都是当前迭代的有效值,所以不会出问题。

解决方法很简单,在循环内部创建一个i的副本,让lambda捕获这个副本:

for (int i = 0; i < scaleActive.Count; i++)
{
    if (scaleActive[i])
    {
        // 创建当前迭代的i的副本
        int currentIndex = i;
        //...
        Task.Run(() => NewportUpload.SendBasket(localTempPath,
            string.Format("{0}{1}", basketNamesBuy[currentIndex], CSV), tradeBasket,
            privateKeyFileName, privateKeyPassphrase, instinetHost, instinetUserName,
            instinetRemotePath));
        //...
    }
}

这样每个后台任务都会捕获到对应迭代的currentIndex值,而不是共享同一个i的引用,就不会出现索引越界的问题了。

内容的提问来源于stack exchange,提问作者jgriffo1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 02:25:59