2
private static Int64 DirectoryBytes(String path) 
    { 
     var files = Directory.EnumerateFiles(path); 
     Int64 masterTotal = 0; 
     ParallelLoopResult result = Parallel.ForEach<String, Int64>(
     files, 
     () => 
     { // localInit: Invoked once per task at start 
      // Initialize that this task has seen 0 bytes 
      return 0; // Set taskLocalTotal initial value to 0 
     }, 
     (file, loopState, index, taskLocalTotal) => 
     { // body: Invoked once per work item 
      // Get this file's size and add it to this task's running total 
      Int64 fileLength = 0; 
      FileStream fs = null; 
      try 
      { 
       fs = File.OpenRead(file); 
       fileLength = fs.Length; 
      } 
      catch (IOException) { /* Ignore any files we can't access */ } 
      finally { if (fs != null) fs.Dispose(); } 
      return taskLocalTotal + fileLength; 
     }, 
     taskLocalTotal => 
     { // localFinally: Invoked once per task at end 
      // Atomically add this task's total to the "master" total 
      Interlocked.Add(ref masterTotal, taskLocalTotal); 
     }); 
     return masterTotal; 
    } 

Ceci est un morceau de code que j'ai obtenu d'un livre. J'ai un doute à ce sujet. La variable tasklocaltotal correspond à un niveau de thread ou un niveau de tâche. Selon le livre, il est au niveau de la tâche, mais comme plusieurs tâches peuvent être exécutées par un thread que comment la variable maintient sa valeur tout au long de l'exécution du programme. Je pense que ça devrait être au niveau du thread. Est-ce que quelqu'un peut donner un aperçu sur ce sujet et d'autres liens possibles à lire où je peux obtenir ce concept plus clair.Parallel.ForEach in .NET 4.0

Répondre

1

The overload of ForEach qui est utilisé ici spécifie que le dernier paramètre est une action appelée pour chaque tâche terminée. Ainsi, à la fin de chaque tâche, le résultat de la tâche est transmis à la méthode Interlocked.Add qui incrémente le total maître avec le total local de cette tâche.

La partie déroutante est cette partie:

taskLocalTotal => 
{ 
    // localFinally: Invoked once per task at end 
    // Atomically add this task's total to the "master" total 
    Interlocked.Add(ref masterTotal, taskLocalTotal); 
} 

il suffit de penser comme (vous pouvez même écrire comme):

x => 
{ 
    // localFinally: Invoked once per task at end 
    // Atomically add this task's total to the "master" total 
    Interlocked.Add(ref masterTotal, x); 
} 

taskLocalTotal a malheureusement le même nom ici comme dans la tâche de action. Donc, ce n'est pas la même variable mais juste le même nom.

+0

Merci Erno pour effacer cela. – Vabs

+0

@Vabs - Pas de problème. En passant, avez-vous remarqué que la page MSDN à laquelle ma réponse renvoie contient presque exactement le même code? –

+0

Ouais. J'ai fait. Le livre qui peut utiliser des exemples de code MSDN comme base pour générer des exemples. – Vabs