2

这是我的代码。在startLog方法中创建的日志文件具有从 1 到 1000 的正确计数,但由log方法创建的日志文件具有重复值。例如,如果重复 88,则错过 89,下一个打印的数字是 90。谁能解释一下为什么会发生这种情况?

          namespace TestThreading
            {
                public partial class Form1 : Form
                {
                    NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
                    public Form1()
                    {
                        InitializeComponent();
                    }

                    private void Form1_Load(object sender, EventArgs e)
                    {
                    }

                    private void button1_Click(object sender, EventArgs e)
                    {
                        new Thread(startLog).Start();
                    }
                    private void startLog()
                    {
                        int i = 0;
                        string str;
                        while (i < 1000)
                        {
                            str = (++i).ToString();
                            logger.Trace(str);
                            Thread t = new Thread(() => log(new TestObject(str)));
                            t.Start();
                        }
                        MessageBox.Show("Done");
                    }
                    private void log(TestObject obj)
                    {
                        logger.Debug(obj.getCount());
                    }
                }

                public class TestObject
                {
                    string count;
                    public TestObject(string i)
                    {
                        count = i;
                    }
                    public string getCount()
                    {
                        return count;
                    }
                }
            }
4

2 回答 2

2

您在str创建新线程时关闭了一个变量 ( ),然后在代码运行之前改变了同一个变量。

请记住,闭包关闭变量而不是 *values。当您的匿名方法确定要传递的内容时,log str已经将其更改为另一个值。

解决方案很简单。只需在循环str 内部定义,以便每个闭包都有自己的变量来关闭:

while (i < 1000)
{
    string str = (++i).ToString();
    logger.Trace(str);
    Thread t = new Thread(() => log(new TestObject(str)));
    t.Start();
}

现在该变量在关闭后永远不会更改;而是为每个闭包创建一个新str变量,每个闭包都有自己的。

于 2013-10-15T20:45:24.333 回答
0

正如 Servy 已经回答的那样,这是因为str变量是在闭包之外定义的

如果需要,您还可以使用ParameterizedThreadStart并传递在循环中修改的变量。这实际上会起作用

    static void Main(string[] args)
    {
        int i = 0;
        string str;
        while (i < 1000)
        {
            str = (++i).ToString();
            Thread t = new Thread((s) => Console.WriteLine(s));
            t.Start(str);
        }

        Console.ReadLine();
    }
于 2013-10-15T20:49:49.977 回答