C# For循环索引超出范围ArgumentOutOfRangeException在多线程时
我有一些奇怪的行为。。。当我在C# For循环索引超出范围ArgumentOutOfRangeException在多线程时,c#,multithreading,exception,lambda,for-loop,C#,Multithreading,Exception,Lambda,For Loop,我有一些奇怪的行为。。。当我在ThreadTest方法中迭代dummyText列表时,我会得到一个索引超出范围异常(ArgumentOutOfRangeException),但是如果我删除线程并只打印文本,那么一切都正常 这是我的主要方法: public static Object sync = new Object(); static void Main(string[] args) { ThreadTest(); Console.WriteLine("Press any ke
ThreadTest
方法中迭代dummyText
列表
时,我会得到一个索引超出范围异常(ArgumentOutOfRangeException
),但是如果我删除线程并只打印文本,那么一切都正常
这是我的主要方法:
public static Object sync = new Object();
static void Main(string[] args)
{
ThreadTest();
Console.WriteLine("Press any key to continue.");
Console.ReadKey();
}
此方法引发异常:
private static void ThreadTest()
{
Console.WriteLine("Running ThreadTest");
Console.WriteLine("Running ThreadTest");
List<String> dummyText = new List<string>()
{ "One", "Two", "Three", "Four", "Five",
"Six", "Seven", "Eight", "Nine", "Ten"};
for (int i = 0; i < dummyText.Count; i++)
{
Thread t = new Thread(() => PrintThreadName(dummyText[i])); // <-- Index out of range?!?
t.Name = ("Thread " + (i));
t.IsBackground = true;
t.Start();
}
}
private static void PrintThreadName(String text)
{
Random rand = new Random(DateTime.Now.Millisecond);
while (true)
{
lock (sync)
{
Console.WriteLine(Thread.CurrentThread.Name + " running " + text);
Thread.Sleep(1000+rand.Next(0,2000));
}
}
}
private static void ThreadTest()
{
Console.WriteLine("Running ThreadTest");
List<String> dummyText = new List<string>()
{ "One", "Two", "Three", "Four", "Five",
"Six", "Seven", "Eight", "Nine", "Ten"};
for (int i = 0; i < dummyText.Count; i++)
{
Console.WriteLine(dummyText[i]); // <-- No exception here
}
}
private static void ThreadTest()
{
Console.WriteLine(“运行线程测试”);
Console.WriteLine(“运行线程测试”);
List dummyText=新列表()
{“一”、“二”、“三”、“四”、“五”,
“六”、“七”、“八”、“九”、“十”};
for(int i=0;i Thread t=新线程(()=>PrintThreadName(dummyText[i]);//当您将局部变量传递到线程或ThreadPool
通过闭包委托时,您需要制作该变量的副本。如中所示:
for (int i = 0; i < dummyText.Count; i++)
{
int index = i;
Thread t = new Thread(() => PrintThreadName(dummyText[index]));
// ...
}
for(int i=0;iPrintThreadName(dummyText[index]);
// ...
}
如果不这样做,那么变量基本上是通过引用传入的,索引将超过for
循环末尾的数组边界(这可能发生在执行闭包之前很久).既然lambda表达式在线程真正启动之前不会被调用,那么复制不应该在lambda表达式之外进行吗?@Michael:哇,我一定是累了,我永远不会写了!谢谢你的快速捕获。你刚刚为我节省了这么多时间和头痛。我已经为此奋斗了好几天,缩小了这个bug的范围。+1