Exporter (0) Imprimer
Développer tout
Cet article a fait l'objet d'une traduction automatique. Déplacez votre pointeur sur les phrases de l'article pour voir la version originale de ce texte. Informations supplémentaires.
Traduction
Source

Comment : gérer des exceptions dans une requête PLINQ

Le premier exemple de cette rubrique indique comment gérer la System.AggregateException qui peut être levée par une requête PLINQ lors de son exécution. Le deuxième exemple montre comment mettre les blocs try-catch dans des délégués, aussi près que possible de l'endroit où l'exception sera levée. De cette façon, vous pouvez les intercepter rapidement voire continuer l'exécution de la requête. Lorsque les exceptions sont autorisées à se propager vers le thread joint, il est possible qu'une requête puisse continuer à traiter des éléments après que l'exception a été levée.

Dans certains cas, lorsque PLINQ revient à l'exécution séquentielle et qu'une exception se produit, l'exception peut être propagée directement et non incluse un wrapper dans une AggregateException. De même, les ThreadAbortException sont toujours propagées directement.

Remarque Remarque

Lorsque l'option "Uniquement mon code" est activée, Visual Studio s'arrête sur la ligne qui lève l'exception et affiche un message d'erreur indiquant que l'exception n'est pas gérée par le code utilisateur. Cette erreur est bénigne. Vous pouvez appuyer sur F5 pour continuer et voir le comportement de gestion des exceptions illustré dans les exemples ci-dessous. Pour empêcher Visual Studio de s'arrêter sur la première erreur, il vous suffit de désactiver la case à cocher "Uniquement mon code" sous Outils, Options, Débogage, Général.

Cet exemple est destiné à montrer l'utilisation et peut ne pas s'exécuter plus rapidement que la requête LINQ to Objects séquentielle équivalente. Pour plus d'informations sur l'accélération, consultez Fonctionnement de l'accélération dans PLINQ.

Cet exemple montre comment mettre les blocs try-catch autour du code qui exécute la requête pour intercepter toute System.AggregateException levée.


// Paste into PLINQDataSample class.
static void PLINQExceptions_1()
{
    // Using the raw string array here. See PLINQ Data Sample.
    string[] customers = GetCustomersAsStrings().ToArray();


    // First, we must simulate some currupt input.
    customers[54] = "###";

    var parallelQuery = from cust in customers.AsParallel()
                        let fields = cust.Split(',')
                        where fields[3].StartsWith("C") //throw indexoutofrange
                        select new { city = fields[3], thread = Thread.CurrentThread.ManagedThreadId };
    try
    {
        // We use ForAll although it doesn't really improve performance
        // since all output is serialized through the Console.
        parallelQuery.ForAll(e => Console.WriteLine("City: {0}, Thread:{1}", e.city, e.thread));
    }

    // In this design, we stop query processing when the exception occurs.
    catch (AggregateException e)
    {
        foreach (var ex in e.InnerExceptions)
        {
            Console.WriteLine(ex.Message);
            if (ex is IndexOutOfRangeException)
                Console.WriteLine("The data source is corrupt. Query stopped.");
        }
    }
}


Dans cet exemple, la requête ne peut pas continuer après la levée de l'exception. Au moment où votre code d'application intercepte l'exception, PLINQ a déjà arrêté la requête sur tous les threads.

L'exemple suivant indique comment mettre un bloc try-catch dans un délégué pour permettre d'intercepter une exception et de continuer l'exécution de la requête.


// Paste into PLINQDataSample class.
static void PLINQExceptions_2()
{

    var customers = GetCustomersAsStrings().ToArray();
    // Using the raw string array here.
    // First, we must simulate some currupt input
    customers[54] = "###";

    // Create a delegate with a lambda expression.
    // Assume that in this app, we expect malformed data
    // occasionally and by design we just report it and continue.
    Func<string[], string, bool> isTrue = (f, c) =>
    {
        try
        {
            string s = f[3];
            return s.StartsWith(c);
        }
        catch (IndexOutOfRangeException e)
        {
            Console.WriteLine("Malformed cust: {0}", f);
            return false;
        }
    };

    // Using the raw string array here
    var parallelQuery = from cust in customers.AsParallel()
                        let fields = cust.Split(',')
                        where isTrue(fields, "C") //use a named delegate with a try-catch
                        select new { city = fields[3] };
    try
    {
        // We use ForAll although it doesn't really improve performance
        // since all output must be serialized through the Console.
        parallelQuery.ForAll(e => Console.WriteLine(e.city));
    }

    // IndexOutOfRangeException will not bubble up      
    // because we handle it where it is thrown.
    catch (AggregateException e)
    {
        foreach (var ex in e.InnerExceptions)
            Console.WriteLine(ex.Message);
    }
}


  • Pour compiler et exécuter ces exemples, copiez-les dans l'exemple de données PLINQ et appelez la méthode Main.

N'interceptez pas d'exception à moins de savoir comment la gérer pour ne pas endommager l'état de votre programme.

Ajouts de la communauté

AJOUTER
Afficher:
© 2014 Microsoft