Parallel.ForEach使用多个线程更改行为

时间:2012-08-13 01:53:35

标签: c# .net multithreading plinq parallel-extensions

我有一个对它们执行写操作的文件数组,我正在使用Parallel.ForEach循环来加快速度。

问题是,当我有多个线程时,它的行为不正常。该程序对WAV文件进行10次写入250000个随机字节,这将导致静态时间约为1.3秒。发生的事情是,多个线程,在绝大多数文件中,没有任何静态,Windows表示文件已经改变,但音频内容没有,另一个问题是一些片段有大约6分钟的静态写入它,这是不可能的,代码只为每个文件写入2500000字节(~10.3秒),因此由于某种原因它将字节写入错误的文件,因此有些没有静态,有些则有荒谬的数量。它不可能错过静电,所以它不可能是我。我知道出事了。

在我多线程化程序之前一切正常,所以我使用MaxDegreeofParallelism = 1并且一切正常,所以我知道问题是由多个线程引起的。

Parallel.ForEach(files, new ParallelOptions{MaxDegreeOfParallelism = 4}, file =>
{
Random rand = new Random();
using (stream = new FileStream(file, FileMode.Open, FileAccess.ReadWrite))
{
FileInfo info = new FileInfo(file);
for (int i = 0; i < 10; i++)
{
    int pos = rand.Next(5000000, Convert.ToInt32(info.Length));
    for (int x = 0; x < 250000; x++)
    {
        byte number = array[rand.Next(array.Length)];
        stream.Seek(pos, SeekOrigin.Begin);
        pos += 4;
        stream.WriteByte(number);
    }
}
}
});

编辑:另一个问题是,对于多个线程,它会写入包含关键数据的标题部分,因此没有媒体播放器识别该格式。这只发生在多个线程上,我忽略了前500万个字节,我知道这已经足够了。

编辑:2更新了代码。

任何人都可以了解一下导致我的代码无法正常运行的多线程的内容吗?

2 个答案:

答案 0 :(得分:3)

Random number generator不是线程安全的。 Jon Skeet有一个good article以及如何创建一个线程安全的随机数生成器。

答案 1 :(得分:3)

{p> streamParallel.ForEach执行的委托声明在Parallel.ForEach创建的所有线程都尝试使用相同的变量。由于没有锁定,因此未定义每个线程将具有的stream值 - 您可能会看到多个线程写入同一个流,这会导致您出现奇怪的多线程行为。

尝试删除委托之外的stream声明,然后更改

using (stream = new FileStream(file, FileMode.Open, FileAccess.ReadWrite))

using (Stream stream = new FileStream(file, FileMode.Open, FileAccess.ReadWrite))