线程开始传递的整数更改超出了应有的范围

时间:2015-05-17 02:50:07

标签: c# multithreading parameters lambda thread-safety

我不知道这是怎么回事。我试图通过产生100个线程来不断地访问它来测试类的线程安全性,但似乎我的匿名方法参数正在改变它们应该永远不会出现的值,我很困惑为什么。由于我不知道发生了什么,我将发布测试中涉及的所有功能。不知何故,我最终得到“线程98”获取参数“num = 100”...这应该是不可能的,我不知道正在发生什么样的hokey pokey正在改变整数。 (在方法“ThreadWriting(int num)”中你会看到我检查“num”等于100的点,在那里我放置一个断点来捕捉行为中的违规线程,并且它每次都会中断。否则它在数组“计数”上抛出一个“IndexOutofRangeException”。我只是想看看我的线程是否通常可以同时访问他们一次尝试使用的类。

    public delegate void TempDel();
    public TempDel InvokeTest;

    public void TRTest3(Form1 sender)
    {
        InvokeTest = new TempDel(UpdateInvoke);

        Thread t = new Thread(() => ConsoleUpdateTest(sender));
        t.IsBackground = true;
        t.Start();

        POConsole.Instance.MaxLines = 20;

        for(int i = 0; i < 100; i++)
        {

            Thread t2 = new Thread(() => ThreadWriting(i));
            t2.IsBackground = true;
            t2.Name = String.Format("Thread {0}", i);
            t2.Start();
        }

    }

    public ulong[] counts = new ulong[100];

    public void ThreadWriting(int num)
    {
        if(num == 100)
        {
            bool stop = true;
        }
        while (true)
        {
            POConsole.Instance.WriteLine("Hello from Thread " + num);
            counts[num]++;
        }
    }

    public void ConsoleUpdateTest(Form1 sender)
    {
        while(true)
        {
            sender.Invoke(InvokeTest);
            Thread.Sleep(5);
        }
    }



    public void UpdateInvoke()
    {
        QuickTestBox.Text = POConsole.Instance.FullFeed;
    }

我所有的线程都被命名,正如你所看到的,并且它们都没有收到名称“Thread 100”,因此我不知道其他线程之一如何传递参数100或参数可能被破坏某种方式。

显然我的线程安全检查在某种程度上不是线程安全的吗?

1 个答案:

答案 0 :(得分:1)

这是一个简单的闭包问题,你不应该使用for循环计数器作为线程参数问题,这里发生问题,因为循环和线程执行不以相同的速度运行,所以i的值可以改变为多个线程:

for(int i = 0; i < 100; i++)
        {

            Thread t2 = new Thread(() => ThreadWriting(i));
            t2.IsBackground = true;
            t2.Name = String.Format("Thread {0}", i);
            t2.Start();
        }

使用以下修改,从循环计数器

创建局部变量
for(int i = 0; i < 100; i++)
        {
            int j = i;
            Thread t2 = new Thread(() => ThreadWriting(j));
            t2.IsBackground = true;
            t2.Name = String.Format("Thread {0}", j);
            t2.Start();
        }