web-dev-qa-db-fra.com

Comment utiliser attendent dans un parallèle foreach?

J'ai donc séparé la meilleure partie de la nuit en essayant de comprendre cela.

J'ai eu la chance de me familiariser avec parallel.foreach hier et cela fonctionne comme je le souhaite, sauf dans un détail.

J'ai ce qui suit:

        Parallel.ForEach(data, (d) =>
        {
            try
            {
                MyMethod(d, measurements);
            }
            catch (Exception e)
            {
              // logg
            }

        });

Dans la méthode "MyMethod", j'ai beaucoup de logique qui se fait et la plupart est bien, mais je fais des appels api où je récupère des données et j'utilise une tâche asynchrone pour que cela puisse utiliser "attendre" afin que le code attendez que cette partie spécifique soit exécutée, puis continuez:

    private async void MyMethod(PimData pimData, IEnumerable<ProductMeasurements> measurements)
    {
        try
        {
           // alot of logic but most relevant part 

            await Task.WhenAll(ExecuteMeasurmentAndChartLogic(pimData.ProductNumber, entity));
            await Task.WhenAll(resourceImportManager.HandleEntityImageFiles(pimData.ProductType + pimData.ProductSize,SwepImageType.Png, ResourceFileTypes.ThreeD, entity, LinkTypeId.ProductResource));

            await Task.WhenAll(resourceImportManager.HandleEntityImageFiles(pimData.ProductSketch, SwepImageType.Png, ResourceFileTypes.Sketch, entity, LinkTypeId.ProductResource));

        }
        catch (Exception e)
        {
            // logg
        }
    }

Problèmes:

1 Pour commencer, la boucle se termine avant que tout le code ne soit terminé

2 Le deuxième problème est que j'obtiens "La tâche a été annulée" dans beaucoup d'appels API

3 Et troisièmement, comme mentionné ci-dessus, le code n'attend pas que chaque méthode s'exécute complètement.

Je n'arrive pas à tout exécuter dans la méthode ExecuteMeasurmentAndChartLogic () avant de passer à l'étape suivante.

Cela me donne les problèmes suivants (plus de problèmes):

Dans cette méthode, je crée un élément et l'ajoute à la base de données, et cet élément a besoin de plus d'informations que j'obtiens à partir d'un appel API qui se fait à l'intérieur de ExecuteMeasurmentAndChartLogic () mais le problème est que plusieurs éléments deviennent fous et doivent attendre le reste des données qui ne sont pas ce que je désire.

NOTE LATÉRALE: Je suis conscient du fait que créer un élément et l'ajouter à la base de données avant qu'il n'y ait toutes les données n'est pas la meilleure pratique mais j'intègre vers PIM et le processus est délicat

Je veux que plusieurs threads s'exécutent mais en même temps, je veux que la logique fuill s'exécute pour chaque élément avant de passer à la méthode suivante.

Clarifier:

Plusieurs éléments en cours d'exécution

Chaque élément manipule TOUS la logique qu'il doit manipuler avant de passer à la partie suivante du code, noramly le fait avec wait.

Dans le code ci-dessus, la méthode resourceImportManager () est exécutée avant la fin d'ExecuteMeasurmentAndChartLogic (). c'est ce que je ne veux pas.

Au lieu d'un Parallel.ForEach, j'ai utilisé:

    Task task1 = Task.Factory.StartNew(() => MyMethod(data, measurements));
    Task.WaitAll(task1);

mais ce n'était pas d'une grande aide

Assez nouveau dans ce domaine et je n'ai pas pu comprendre où je me trompe.

EDIT: mise à jour des problèmes avec ce

EDIT: voici à quoi ressemble ExecuteMeasurmentAndChartLogic ():

    public async Task ExecuteMeasurmentAndChartLogic(string productNumber, Entity entity)
    {
        try
        {
            GrafGeneratorManager grafManager = new GrafGeneratorManager();
            var graphMeasurmentList = await MeasurmentHandler.GetMeasurments(productNumber);

            if (graphMeasurmentList.Count == 0) return;

            var chart = await grafManager.GenerateChart(500, 950, SystemColors.Window, ChartColorPalette.EarthTones,
                "legend", graphMeasurmentList);

            await AddChartsAndAddToXpc(chart, entity, productNumber);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }

    }

EDIT: Contexte de ceci: je fais un appel à une API pour obtenir beaucoup de données. Pour chaque élément de ces données, je dois effectuer un appel API et obtenir les données que j'applique à l'élément.

Après avoir lu des commentaires qui m'ont également fait réfléchir différemment. Je peux peut-être parcourir tous mes éléments et faire une logique mineure pour eux et ajouter une URL dans une liste de tâches et créer une tâche distincte qui exécute celle-ci une par une.

Je garderai cela à jour

7
ThunD3eR

N'utilisez pas Parralel.ForEach du tout. Faites votre méthode pour retourner la tâche au lieu de l'annuler, collectez toutes les tâches et attendez-les comme:

Task.WaitAll(data.Select(d => MyMethod(d, someParam)).ToArray());
14
Eduard Lepner