2012-07-05 102 views
0

我希望有人可以幫助我,如果有關於使用多個線程/任務寫入文件的問題。請參閱下面我的代碼示例...多線程寫入字節[]到文件

AddFile返回保持的值多頭的排列,blobNumber的斑點和數據寫入到BLOB大小內側補償

public long[] AddFile(byte[] data){ 
    long[] values = new long[3]; 

    values[0] = WorkingIndex = getBlobIndex(data); //blobNumber 
    values[1] = blobFS[WorkingIndex].Position; //Offset 
    values[2] = length = data.length; //size 

    //BlobFS is a filestream 
    blobFS[WorkingIndex].Write(data, 0, data.Length); 

    return values; 
} 

因此,可以說我在像下面這樣的foreach循環中使用AddFile函數。

List<Task> tasks = new List<Task>(System.Environment.ProcessorCount); 
foreach(var file in Directory.GetFiles(@"C:\Documents"){ 
    var task = Task.Factory.StartNew(() => { 
     byte[] data = File.ReadAllBytes(file); 
     long[] info = blob.AddFile(data); 
     return info 
    }); 
    task.ContinueWith(// do some stuff); 
    tasks.Add(task); 
} 
Task.WaitAll(tasks.ToArray); 
return result; 

我可以想像,這將完全失敗,因爲文件將互相覆蓋BLOB中由於事實寫入功能還沒有寫完文件1和其他任務在被寫入文件2路同一時間。

那麼解決這個問題的最好方法是什麼?也許使用異步寫功能...

您的幫助,將不勝感激! 親切的問候, 馬亭

+1

.NET 4.5將提供異步文件I/O本身,它是更好地保持同步的東西的那一刻(你寫無論如何都是同一個物理驅動器,所以操作無法首先進行並行化)。 – Alex

回答

1

我在這裏的建議是運行這些任務並行。很可能磁盤IO將成爲任何基於文件的操作的瓶頸,因此並行運行它們只會導致每個線程被阻止訪問磁盤。最終,你很可能會發現你的代碼運行速度比你寫的代碼慢得多,而不是串行運行。

是否有一個特別的原因,你想要這些並行?你可以連續處理磁盤寫入,只需在不同的線程上調用ContinueWith()?這也有利於消除您發佈的問題。

編輯:for循環的示例天真重新實現:

foreach(var file in Directory.GetFiles(@"C:\Documents"){ 
    byte[] data = File.ReadAllBytes(file); // this happens on the main thread 

    // processing of each file is handled in multiple threads in parallel to disk IO 
    var task = Task.Factory.StartNew(() => { 
     long[] info = blob.AddFile(data); 
     return info 
    }); 
    task.ContinueWith(// do some stuff); 
    tasks.Add(task); 
} 
+0

我只想從我的應用程序中獲得最大性能。我需要處理大量的文件,我可以改進的過程中的每一步都希望能夠加速這個過程。但是你說得對,這可能會導致I/O瓶頸。你能解釋一下你的意思嗎?「你可以連續處理磁盤寫入操作,只需在不同的線程上調用ContinueWith(),而不是?」 TNX! – Martijn

+0

請參閱我的編輯,瞭解我的意思。 –