Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.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_Loops - Fatal编程技术网

C# 多线程时出现意外结果

C# 多线程时出现意外结果,c#,multithreading,loops,C#,Multithreading,Loops,我有一个函数,由一个用start和end参数启动的线程调用。该函数在单主线程上运行时工作正常。但是,当我尝试在它上使用多线程时,代码会中断 功能如下: static void processThread(long startLimit, long endLimit) { long rangeLimit = startLimit; while (startLimit < endLimit) { rangeLimit = rang

我有一个函数,由一个用start和end参数启动的线程调用。该函数在单主线程上运行时工作正常。但是,当我尝试在它上使用多线程时,代码会中断

功能如下:

static void processThread(long startLimit, long endLimit)
    {
        long rangeLimit = startLimit;
        while (startLimit < endLimit) {
            rangeLimit = rangeLimit + 100;
            startLimit++;
            Console.WriteLine("Processed for " + startLimit + ", " + rangeLimit); 
            startLimit = rangeLimit;
        }
    }
等等。。。但我得到的是:

Started for 0, 2500
Started for 2500, 5000
Processed for 5001, 5100
Processed for 5101, 5200
Processed for 5201, 5300
Processed for 5301, 5400
Processed for 5401, 5500
Processed for 5501, 5600
Processed for 5601, 5700
Processed for 5001, 5100
Started for 5000, 7500
Processed for 5001, 5100
Processed for 5101, 5200
Processed for 5201, 5300
Processed for 5301, 5400
Processed for 5401, 5500
Processed for 5501, 5600
Processed for 5601, 5700
Processed for 5701, 5800
Processed for 5801, 5900
Processed for 5901, 6000
Processed for 6001, 6100
Processed for 6101, 6200
Started for 7500, 10000
Processed for 6201, 6300
Processed for 6301, 6400
Processed for 6401, 6500
Processed for 6501, 6600
Processed for 5701, 5800
它有许多重复值,并且没有0-2500范围内的值。我还尝试了Task.Factory,得到了相同的结果


在此方面的任何帮助都将不胜感激。

我不会对您的问题的正确解决方案发表评论,只是为了修复您的输出,您在结束时错过了这一点,以便在所有子线程完成之前阻止主线程:

                Console.WriteLine("Started for " + startPoints[i] + ", " + endPoints[i]);
        }
        foreach (var thread in threads)
        {
            thread.Join();
        }

        Console.ReadKey();
    }
我在代码中还修复了一件事:

            int count = i;
            threads[i] = new Thread(() =>
            {
                processThread(startPoints[count], endPoints[count]);
            });
防止从子线程求值时i无效的潜在问题

我还想说,除非您真的需要使用“旧的”.net线程,否则应该像其他评论者所建议的那样使用并行库或任务

同样的只是用任务方法重写(为了更好地说明,我保留了它,只是用任务替换了线程)

var factory=new TaskFactory();
var tasks=新列表();
对于(int i=0;i
{
processThread(起点[count],终点[count]);
});
任务。添加(任务);
WriteLine(“为“+startPoints[i]+”、“+endPoints[i])启动);
}
Task.WaitAll(tasks.ToArray());

我运行了你的代码,在启动线程时,实际上得到了一个索引越界异常。然而,这对我起了作用:

Thread[] threads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
    var start = startPoints[i];
    var end = endPoints[i];
    threads[i] = new Thread( () => processThread( start, end ) );
    threads[i].Start();
    Console.WriteLine( "Started for " + startPoints[i] + ", " + endPoints[i] );
}
Thread[]threads=新线程[threadCount];
对于(int i=0;iprocessThread(开始,结束));
线程[i].Start();
WriteLine(“为“+startPoints[i]+”、“+endPoints[i])启动);
}

问题可能是,当线程访问代码中的
startPoints[i]
时,主线程中的
i
已经更改了。

作为旁白:如果这确实是您想要并行化的工作,请使用
Parallel.ForEach
而不是编写您自己的分区代码。要正确理解并不容易,所以最好有框架代码。您在带有“Started for…”的行中看到了什么?@OfirWinegarten编辑后将实际结果添加到问题中。。感谢问题是由“捕获循环变量”引起的。Henk是正确的。这里的基本问题是
i
是在线程运行时计算的,而不是在创建委托时计算的。它读取
i
的当前值,这几乎肯定高于创建代理时的值。感谢您回复@Bobo,正如我在问题中提到的,我尝试过使用任务,但没有成功。工厂尝试在我的编辑器中进行了注释,因为它被证明是无用的。嘿,Bobo,您关于为任务声明变量的建议”“伯爵“工作得很好。非常感谢你的帮助!我运行了他的原始版本,并有一个问题,我将是出界。这个竞赛条件是如何产生的,为什么你的修正能起作用?如果您有一个线程数组,其中您在一个for循环中创建了线程,而在另一个for循环中启动了线程,那么这为什么不能修复争用条件呢?我是如何进入这个匿名函数的?我在哪里可以读到更多关于它是如何工作的?@WithMetta这简要地解释了:主要的一点是,lambda是在执行子线程/任务体时计算的,从那时起,变量已经被主线程for循环更改了。这是一个正确的答案。创建lambda时,lambda不会复制
i
。lambda在执行时读取
i
的当前值,但到那时,
i
比创建委托时大得多。@Mats391,非常感谢您的帮助。这个答案同样有效。
            int count = i;
            threads[i] = new Thread(() =>
            {
                processThread(startPoints[count], endPoints[count]);
            });
var factory = new TaskFactory();
        var tasks = new List<Task>();
        for (int i = 0; i < threadCount; i++)
        {
            int count = i;
            Task task = factory.StartNew(() =>
            {
                processThread(startPoints[count], endPoints[count]);
            });
            tasks.Add(task);
            Console.WriteLine("Started for " + startPoints[i] + ", " + endPoints[i]);
        }

        Task.WaitAll(tasks.ToArray());
Thread[] threads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
    var start = startPoints[i];
    var end = endPoints[i];
    threads[i] = new Thread( () => processThread( start, end ) );
    threads[i].Start();
    Console.WriteLine( "Started for " + startPoints[i] + ", " + endPoints[i] );
}