2012-12-06 38 views
0

我是一名初級程序員,我試圖解決一個任務。使用c#.net 4.0我正在運行文件夾,選擇所有* .xml文件,並將每個文件寫入具有新擴展名* .bin的新文件夾。對於每個文件在寫之前我正在應用算法,這是由另一個程序員編寫的,我不知道它的實現。如何使用類任務進行並行處理

所以我讀* .xml文件,反序列化並將其寫入新的* .bin文件。當我沒有使用並行編程時,對於2000個文件我有1分鐘的時間。現在我決定使用並行編程任務。現在我爲每個文件創建新的任務(所有進程(讀取 - 反序列化 - 寫入)在一個任務中),現在我有40秒。但我認爲並行編程幫助我將時間縮短到25-30秒。

請給我你的評論我做錯了什麼,以及我如何去實現這一點。謝謝。

byte[] buffer; 
using (Stream stream = new FileInfo(file).OpenRead()) 
{ 
    buffer = new byte[stream.Length]; 
    stream.Read(buffer, 0, (int)stream.Length); 
} 

foreach (var culture in supportedCultures) 
{ 
    CultureInfo currentCulture = culture; 
    Tasks.Add(Task.Factory.StartNew(() => 
    { 
     var memoryStream = new MemoryStream(buffer); 
     Task<object> serializeTask = Task.Factory.StartNew(() => 
     { 
      return typesManager.Load(memoryStream, currentCulture); 
     }, TaskCreationOptions.AttachedToParent); 

     string currentOutputDirectory = null; 
     if (outputDirectory != null) 
     { 
      currentOutputDirectory = outputDirectory.Replace(PlaceForCultureInFolderPath, 
                   currentCulture 
                    .ToString()); 
      Directory.CreateDirectory(currentOutputDirectory); 
     } 

     string binFile = Path.ChangeExtension(Path.GetFileName(file), ".bin"); 
     string binPath = Path.Combine(
      currentOutputDirectory ?? Path.GetDirectoryName(file), 
      binFile); 

     using (FileStream outputStream = File.OpenWrite(binPath)) 
     { 
      try 
      { 
       new BinaryFormatter().Serialize(outputStream,serializeTask.Result); 
      } 
      catch (SerializationException e) 
      { 
       ReportCompilationError(e.Message, null); 
      } 
     } 
    })); 
} 
+2

請提供一些代碼 –

回答

1

第一。不能保證TPL能夠提供任何性能。
正如喬恩所說,寫入硬盤可能會降低性能,除非操作系統將這些文件緩存以備以後順序寫入。絕對的緩存大小有其限制。

二。默認調度程序面向利用CPU內核,所以有可能只有幾個任務被並行處理,而其他人則排隊等待。您可以通過明確設置ParallelOptions.MaxDegreeOfParallelism或在查詢中調用WidthDegreeOfParallelism()來更改此默認值。仍然是調度程序誰決定並行運行多少個任務。

有關於多線程的一個很好的免費book。網

3

沒有看到代碼或不知道什麼任務真的在做,我們所能做的就是提供一些相當一般的建議和診斷。

您的代碼是CPU綁定的還是IO綁定的? (您應該可以通過查看性能監視器並查看運行代碼時CPU的繁忙程度來了解這一點。)

如果您的代碼是IO綁定的,並且您在單個物理上有多個文件非SSD驅動器,然後將這些工作並行進行可能會讓你變得更糟,因爲你迫使驅動器頭在各處繼續點擊。

如果你的代碼是CPU綁定,然後並行應該來幫助(這些聽起來像獨立的任務) - 再次,你應該能夠通過運行代碼首先不併行,然後並行講這個,在這兩種情況下看CPU圖。你會期望在串行版本中,一次只有一個CPU「繁忙」,而在並行版本中,所有CPU應該是繁忙的。

+0

喬恩,謝謝 - 我已經注意到比並行版本處理器的每個核心都加載了70-80%。這是不夠的,但也許你是對的,HDD不能這麼快寫出這麼多文件。 –

2

Task.Factory

var task1 = Task.Factory.StartNew(() => 
    { 
     //some oepratation 
    }); 
    var task2 = Task.Factory.StartNew(() => 
    { 
     //some operations 
    }); 
    Task.WaitAll(task1, task2); 

但這不會保證一個新的線程爲每一個任務,因爲它使用可用的線程,只是時間表的工作或任務分配給任何線程available.Hence,我建議你使用Parallel.ForEach

var options = new ParallelOptions { MaxDegreeOfParallelism = 2 // or more }; 
Parallel.ForEach (list, options, a=> { }); 

http://msdn.microsoft.com/en-us/library/system.threading.tasks.parallel.foreach.aspx