2012-08-13 45 views
1

我有一个文件的数组正在对它们执行写操作,我正在使用Parallel.ForEach循环来加速。Parallel.ForEach更改行为与多个线程

问题是,当我有多个线程时,它的行为不正常。该程序将10万个随机字节写入WAV文件,这会导致静态约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更新的代码。

任何人都可以阐明它是关于多线程导致我的代码无法正常工作?

+1

@spender是不是他在每次迭代递增POS 4? – Adam 2012-08-13 02:00:37

+0

...是的,我的不好。不理我。 – spender 2012-08-13 02:01:04

+0

您实际上没有显示Parallel.ForEach()位。 – 2012-08-13 02:01:40

回答

3

stream被宣布为外部正在执行的代表Parallel.ForEach。由Parallel.ForEach创建的所有线程都试图使用相同的变量。由于没有锁定,所以它没有定义每个线程会有什么值stream - 您可能会看到多个线程写入同一个流,这会导致您的奇怪的多线程行为。

尝试删除stream外委托的声明,并改变

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

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

我总是盯着问题,但我似乎无法看到它。它现在正在写入所有文件,并且标题保持不变,谢谢。 – 2012-08-13 05:19:22

3

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

+0

我更新了代码,我没有复制所有内容。 Rand被声明为线程静态,并为每个文件生成一个新实例;我需要做更多的事情来保证线程安全吗? – 2012-08-13 02:24:55

+1

我不认为这会起作用。用'Random rand = new Random();'在'.ForEach()'中声明你的随机数发生器,而不是让它成为一个类级变量。我不认为如果ThreadStaticAttribute在非静态变量上,它不会执行任何操作(请参阅:http://stackoverflow.com/questions/5227676/how-does-the-threadstatic-attribute-work#5227784) – 2012-08-13 02:32:40

+0

我试过了在'Parallel.ForEach'循环中实例化rand,但没有效果,问题仍然存在。但是当我再次进行测试时,它引发了另一个我忘记的问题,写下文件头部分,使其不可读。我的问题中的代码已更新。 – 2012-08-13 03:14:37