对于循环索引超出范围ArgumentOutOfRangeException的多线程时 [英] For loop index out of range ArgumentOutOfRangeException when multithreading

查看:541
本文介绍了对于循环索引超出范围ArgumentOutOfRangeException的多线程时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我收到一些奇怪的行为...当我在<$遍历 dummyText 列表 C $ C> ThreadTest 方法,我得到一个索引超出范围的异常( ArgumentOutOfRangeException )的,但如果我删除线程和我刚刚打印出来的。文字,然后一切工作正常。

I'm getting some strange behavior... when I iterate over the dummyText List in the ThreadTest method I get an index out of range exception (ArgumentOutOfRangeException), but if I remove the threads and I just print out the text, then everything works fine.

这是我的主要方法:

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
    }
}



有谁知道为什么会这样?

Does anybody know why this is happening?

推荐答案

当你传递一个局部变量成线或线程池委托通过关闭,你需要做的变量的副本。如:

When you pass a local variable into a thread or ThreadPool delegate through a closure, you need to make a copy of the variable. As in:

for (int i = 0; i < dummyText.Count; i++)
{
    int index = i;
    Thread t = new Thread(() => PrintThreadName(dummyText[index]));
    // ...
}

如果你不这样做,则变量基本上被通过引用传递中,索引将在循环的末尾(可能倒闭不久发生超过数组的边界是不断执行)。

If you don't do this, then the variable basically gets passed in by reference, and the index will exceed the bounds of the array at the very end of the for loop (which may happen long before the closure is ever executed).

这篇关于对于循环索引超出范围ArgumentOutOfRangeException的多线程时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆