2012-08-13 155 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