Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将列表用作线程启动例程的参数时,索引超出范围错误_C#_Multithreading_Lambda_Delegates_Indexoutofboundsexception - Fatal编程技术网

C# 将列表用作线程启动例程的参数时,索引超出范围错误

C# 将列表用作线程启动例程的参数时,索引超出范围错误,c#,multithreading,lambda,delegates,indexoutofboundsexception,C#,Multithreading,Lambda,Delegates,Indexoutofboundsexception,我正在编写一个C#程序,该程序要求为函数提供一个线程参数,以便该函数在单独的线程上正常运行。具体来说,其中一个参数是它应该访问的文件的字符串名称。问题是,我正在将文件名存储在一个列表中,并且正在访问列表中的值。然而,当我这样做时,在创建一个或两个线程之后,我会得到一个索引超出范围的错误。我认为这是字符串列表是我的问题,但我知道索引并没有超出范围 我不确定我传递参数的方式是否有问题,或者可能有什么问题 下面是我的C#代码示例(不包括所调用函数的代码): for(int i=0;irunGnuplo

我正在编写一个C#程序,该程序要求为函数提供一个线程参数,以便该函数在单独的线程上正常运行。具体来说,其中一个参数是它应该访问的文件的字符串名称。问题是,我正在将文件名存储在一个列表中,并且正在访问列表中的值。然而,当我这样做时,在创建一个或两个线程之后,我会得到一个索引超出范围的错误。我认为这是字符串列表是我的问题,但我知道索引并没有超出范围

我不确定我传递参数的方式是否有问题,或者可能有什么问题

下面是我的C#代码示例(不包括所调用函数的代码):

for(int i=0;i<5;i++)
{
添加(String.Format(surfacePlotDataLocation+“ThreadData{0}.txt”,i));
尝试
{
generateInputFile(主数据位置);
}
抓住
{
Show(“剩余数据不足,无法创建输入文件”);
masterDataLocation=masterDataSet.Count-((graphData.NumRootsUsed+1)*(graphData.polymone+1)-1);
this.dataSetLabel.Text=String.Format(“当前数据集:{0}”,masterDataLocation+1);
返回;
}
尝试
{
//我希望在特定的文本文件中创建数据
createSurfaceGraph(surfaceGraphDataNames[i]);
//开始线程
添加(新线程(()=>runGnuplotClicks(surfaceGraphDataNames[i],masterDataLocation));
线程运行[i]。开始();
}
抓住
{
this.graphPictureBox1.Image=null;//在数据失败时使图像消失
MessageBox.Show(“Gridgen未能生成良好数据”);
}
masterDataLocation++;
}

我遇到了这样的问题,然后我使用了线程。我确信指数没有超出范围,如果我试图在突破点停下来然后继续,这种情况就不会发生。
尝试使用任务而不是线程。它起作用了

看起来你必须这样做:

threadsRunning.Add(new Thread(() => {
           var k = i;
           runGnuplotClicks(surfaceGraphDataNames[k], masterDataLocation)
          }
        ));
原因是当您使用变量
i
时,它是不安全的,因为当
i++
surfaceGraphDataNames
尚未添加新项时,将引发异常,因为
线程几乎同时运行

以下是导致异常的上下文:

for(int i = 0; i < 5; i++){
   //Suppose i is increased to 3 at here
   //Here is where your Thread running code which accesses to the surfaceGraphDataNames[i]   
   //That means it's out of range at this time because
   //the surfaceGraphDataNames has not been added with new item by the code below 
   surfaceGraphDataNames.Add(String.Format(surfacePlotDataLocation+"ThreadData{0}.txt", i));
   //....
}
同步尝试:
Queue q=新队列();
对于(int i=0;i<5;i++){
//.....
q、 排队(i);
线程运行。添加(新线程(()=>{
runGnuplotClicks(surfaceGraphDataNames[q.Dequeue()],masterDataLocation)
}
));
线程运行[i]。开始();
}

最明显的问题是你是。构造lambda表达式时,任何变量引用都指向变量本身,而不是其值。请考虑以下示例中的代码。

for (int i = 0; i < 5; i++)
{
  // Code omitted for brevity.

  new Thread(() => runGnuplotClicks(surfaceGraphDataNames[i], masterDataLocation))

  // Code omitted for brevity.
}

您的代码中一定有错误,当它抛出异常并突出显示错误的位置时,您应该将鼠标移到列表和索引变量上查看。索引变量总是超出列表的范围,这是事实。我不确定你所说的索引变量总是超出列表的范围是什么意思?当我将值发送到控制台而不是线程部分时,我没有索引超出范围的问题。此外,我也不明白为什么无论我将try-catch块放在何处,我似乎都无法捕获异常。异常未得到处理。我指的是用作列表
索引器中传递的索引的变量,例如,它是代码中的
I
。有一些异常,
try-catch
无法捕获,我认为它可能涉及
Debug->Exceptions
中的一些选项,您可能想尝试勾选第一行的
抛出的
列。奇怪的是,我非常确定我没有超出范围,因为我尝试将列表从lambda表达式中索引出来,并且没有抛出异常,因此我不确定为什么会出现此问题。不幸的是,这似乎无法解决任何问题。“谢谢你,”杰克哈特说,“这是我能想到的唯一原因。我使用的代码也是处理线程时的
安全方法。@JakeGearhart您应该在
runGnuplotClicks
中显示代码,我想您可以使用
masterDataLocation
作为索引。是的,我想这与此有关。我发现,如果我使用thread.sleep(500),它可以继续运行而不会失败,这一定是因为我给了一个使用它的线程一个值。我首先假设它不会有问题,但现在我意识到线程使用该值的速度一定太快了。我仍然不知道如何修复它,但我会继续努力。@JakeGearhart您可能想在我的更新中看到最后一次使用同步的尝试。希望它现在能工作。谢谢这是类似于国王的回答,我现在能让它工作了。
var j = i;
threadsRunning.Add(new Thread(() => {
     var k = j;
     runGnuplotClicks(surfaceGraphDataNames[k], masterDataLocation)
    }
));
Queue<int> q = new Queue<int>();
for(int i = 0; i < 5; i++){
  //.....
  q.Enqueue(i);
  threadsRunning.Add(new Thread(() => {       
     runGnuplotClicks(surfaceGraphDataNames[q.Dequeue()], masterDataLocation)
    }
  ));
  threadsRunning[i].Start();
}
for (int i = 0; i < 5; i++)
{
  // Code omitted for brevity.

  new Thread(() => runGnuplotClicks(surfaceGraphDataNames[i], masterDataLocation))

  // Code omitted for brevity.
}
for (int i = 0; i < 5; i++)
{
  // Code omitted for brevity.

  int capture = i;
  new Thread(() => runGnuplotClicks(surfaceGraphDataNames[capture], masterDataLocation))

  // Code omitted for brevity.
}