80 votes

La façon la plus simple d'exécuter trois méthodes en parallèle en C#

J'ai trois méthodes que j'appelle pour faire des calculs, à savoir

results.LeftFront.CalcAi();  
results.RightFront.CalcAi();  
results.RearSuspension.CalcAi(geom, vehDef.Geometry.LTa.TaStiffness, vehDef.Geometry.RTa.TaStiffness);

Chacune des fonctions est indépendante des autres et peut être calculée en parallèle sans blocage.
Quel est le moyen le plus simple de les calculer en parallèle sans que la méthode de contention ne se termine avant que les trois ne soient terminées ?

0 votes

Vous n'êtes intéressé que par la solution de la librairie parallèle des tâches ? Que diriez-vous d'un simple Delegate.BeginInvoke() ou même Thread.Start() ?

0 votes

Il veut attendre tous les résultats - vous pouvez le faire avec ce que vous suggérez mais vous devez faire la synchronisation vous-même - IMHO vous devriez utiliser Task tant qu'il n'y a pas de très bonnes raisons de ne pas le faire - cela deviendra encore plus important si C#/async est mis en service

0 votes

Tous les exemples de début de fil que j'ai trouvés n'attendent pas que le groupe de fonctions soit complet.

138voto

Sander Rijken Points 15425

Voir le Documentation sur le TPL . Ils listent cet échantillon :

Parallel.Invoke(() => DoSomeWork(), () => DoSomeOtherWork());

Dans votre cas, cela devrait donc fonctionner :

Parallel.Invoke(
    () => results.LeftFront.CalcAi(),
    () => results.RightFront.CalcAi(),
    () => results.RearSuspension.CalcAi(geom, 
                                        vehDef.Geometry.LTa.TaStiffness, 
                                        vehDef.Geometry.RTa.TaStiffness));

EDITAR: L'appel revient après que toutes les actions ont fini de s'exécuter. Invoke() ne garantit pas qu'elles seront effectivement exécutées en parallèle, ni l'ordre d'exécution des actions.

5 votes

Cela attendra-t-il que toutes les tâches parallèles soient terminées ?

2 votes

Malgré toutes les recherches que j'ai effectuées, il semble que la plupart des gens aient omis cet exemple simple. Merci pour votre réponse rapide et votre excellente réponse.

5 votes

@Jonathan Il attendra. La construction est similaire à celle qui consiste à lancer plusieurs tâches puis à appeler Task.WaitAll .

26voto

Carsten König Points 14720

Vous pouvez également le faire avec les tâches (plus agréable si vous avez besoin ultérieurement d'une annulation ou d'un résultat similaire).

var task1 = Task.Factory.StartNew(() => results.LeftFront.CalcAi());
var task2 = Task.Factory.StartNew(() => results.RightFront.CalcAi());
var task3 = Task.Factory.StartNew(() =>results.RearSuspension.CalcAi(geom, 
                              vehDef.Geometry.LTa.TaStiffness, 
                              vehDef.Geometry.RTa.TaStiffness));

Task.WaitAll(task1, task2, task3);

7 votes

Ce n'est peut-être pas une bonne idée d'utiliser start new see : ( blog.stephencleary.com/2013/08/nouveau départ-est-dangereux.html )

4 votes

@dotNETNinja vrai maintenant - cette réponse est assez ancienne (comme vous pouvez le voir) - il n'y avait pas d'async à l'époque - de toute façon, vous pouvez simplement le changer avec Task.Run comme conseillé par le lien que vous avez fourni - étant donné que vous pouvez utiliser .net4.5 (ou plus récent)

0 votes

J'ai quelque chose de similaire ici.. stackoverflow.com/questions/30261335/

3voto

Shiraz Bhaiji Points 34901

Dans .NET 4, Microsoft a introduit la bibliothèque parallèle de tâches qui a été conçue pour gérer ce type de problème, voir Programmation parallèle dans le cadre de .NET .

3voto

nvivekgoyal Points 434

Pour exécuter des méthodes parallèles indépendantes les unes des autres, on peut également utiliser ThreadPool.QueueUserWorkItem. Voici l'exemple de méthode

public static void ExecuteParallel(params Action[] tasks)
{
    // Initialize the reset events to keep track of completed threads
    ManualResetEvent[] resetEvents = new ManualResetEvent[tasks.Length];

    // Launch each method in it's own thread
    for (int i = 0; i < tasks.Length; i++)
    {
        resetEvents[i] = new ManualResetEvent(false);
        ThreadPool.QueueUserWorkItem(new WaitCallback((object index) =>
            {
                int taskIndex = (int)index;

                // Execute the method
                tasks[taskIndex]();

                // Tell the calling thread that we're done
                resetEvents[taskIndex].Set();
            }), i);
    }

    // Wait for all threads to execute
    WaitHandle.WaitAll(resetEvents);
}

Vous trouverez plus de détails sur cette fonction ici :
http://newapputil.blogspot.in/2016/03/running-parallel-tasks-using.html

0voto

Brett Mealor Points 81
var task1 = SomeLongRunningTask();
var task2 = SomeOtherLongRunningTask();

await Task.WhenAll(task1, task2);

L'avantage de cette méthode par rapport à Task.WaitAll est qu'elle libère le fil et attend l'achèvement des deux tâches.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X