2010-07-31 4 views
1

J'ai travaillé sur un exemple dans le livre de texte sur la programmation parallèle en C#. Le livre suggère Parallel.Invoke peut remplacer la création, l'invocation et l'attente des tâches. Cependant, j'ai essayé et trouvé que si j'utilise Parallel.Invoke, les tâches ne finiraient pas avant de retourner une valeur. Mais en théorie, Parallel.Invoke devrait toujours attendre.Pourquoi Parallel.Invoke ne parvient pas à terminer toutes les actions?

Le code:

private byte[] getDataForGraph(int dataSize) 
    { 
     byte[] data = new byte[dataSize]; 


     Parallel.Invoke(
      () => Task.Factory.StartNew(() => generateGraphData(data, 0, pixelWidth/8)), 
      () => Task.Factory.StartNew(() => generateGraphData(data, pixelWidth/8, 
       pixelWidth/4)), 
      () => Task.Factory.StartNew(() => generateGraphData(data, pixelWidth/4, 
       pixelWidth * 3/8)), 
      () => Task.Factory.StartNew(() => generateGraphData(data, pixelWidth * 3/8, 
       pixelWidth/2))); 

     return data; 
    } 

Et la façon d'exécuter la fonction:

Task<byte[]> getDataTask = Task<byte[]>.Factory.StartNew(() => getDataForGraph(dataSize)); 
byte[] data = getDataTask.Result; 

Le private void generateGraphData(byte[] data, int partitionStart, int partitionEnd) est une fonction qui remplit le tableau de données, de partitionStart à partitionEnd.

Si je lance le programme, seule une partie de la matrice est remplie. Mais si je remplace Invoke avec

Task first = Task.Factory.StartNew(() => generateGraphData(data, 0, pixelWidth/8)); 
Task second = Task.Factory.StartNew(() => generateGraphData(data, pixelWidth/8, pixelWidth/4)); 
Task third = Task.Factory.StartNew(() => generateGraphData(data, pixelWidth/4, pixelWidth * 3/8)); 
Task fourth = Task.Factory.StartNew(() => generateGraphData(data, pixelWidth * 3/8, pixelWidth/2)); 
Task.WaitAll(first, second, third, fourth); 

Le programme se déroule comme prévu (le tableau est complètement rempli).

Quel peut-être le problème ici?

Merci d'avance.

Répondre

5

Il exécute les actions jusqu'à ce qu'elles soient terminées. Dans votre cas, chaque action doit appeler Task.Factory.StartNew(...) - et que a complété; cependant, il n'y a aucune garantie que chacune des tâches a été mise en file d'attente/traitée pour le moment. La différence est WaitAll (que vous n'avez pas appelée dans votre exemple Parallel).

Une option serait ici de réduire à:

Parallel.Invoke(
    () => generateGraphData(data, 0, pixelWidth/8), 
    () => generateGraphData(data, pixelWidth/8, pixelWidth/4), 
    () => generateGraphData(data, pixelWidth/4, pixelWidth * 3/8), 
    () => generateGraphData(data, pixelWidth * 3/8, pixelWidth/2) 
); 
+0

Merci, qui explique beaucoup. Je viens de copier le code, et je ne l'ai pas vérifié attentivement. – LLS

Questions connexes