Nasıl yapılır: PLINQ Sorgusunda Özel Durumları İşleme

Bu konudaki ilk örnek, yürütülürken bir PLINQ sorgusundan oluşturulabilecek öğesinin nasıl işleneceğini System.AggregateException gösterir. İkinci örnekte, özel durumun oluşturulacağı yere olabildiğince yakın olan try-catch bloklarının temsilciler içinde nasıl yerleştirileceği gösterilmektedir. Bu şekilde, bunları oluştukları anda yakalayabilir ve sorgu yürütmeye devam edebilirsiniz. Özel durumların birleştirilmiş iş parçacığına geri dönmesine izin verildiğinde, bir sorgu özel durum oluşturduktan sonra bazı öğeleri işlemeye devam edebilir.

BAZı durumlarda PLINQ sıralı yürütmeye geri döndüğünde ve bir özel durum oluştuğunda, özel durum doğrudan yayılabilir ve içine AggregateExceptionsarmalanmayabilir. Ayrıca, ThreadAbortExceptions her zaman doğrudan yayılır.

Not

"Yalnızca Benim Kodum" etkinleştirildiğinde, Visual Studio özel durumu oluşturan satırda kırılır ve "özel durum kullanıcı kodu tarafından işlenmez" hata iletisini görüntüler. Bu hata zararsızdır. F5 tuşuna basarak devam edebilir ve aşağıdaki örneklerde belirtilen özel durum işleme davranışını görebilirsiniz. Visual Studio'nun ilk hatada hata vermesini önlemek için Araçlar, Seçenekler, Hata Ayıklama, Genel altındaki "Yalnızca Kodum" onay kutusunun işaretini kaldırması gerekir.

Bu örnek kullanımı göstermek için tasarlanmıştır ve eşdeğer sıralı LINQ to Objects sorgusundan daha hızlı çalışmayabilir. Hızlandırma hakkında daha fazla bilgi için bkz . PLINQ'ta Hızlandırmayı Anlama.

Örnek 1

Bu örnekte, sorguyu yürüten kodun etrafında try-catch bloklarının nasıl yerleştirildiğinden ve bu blokların atılan kodlara System.AggregateExceptionnasıl yakalanacağınız gösterilmektedir.

// 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 corrupt 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.");
        }
    }
}
' Paste into PLINQDataSample class
Shared Sub PLINQExceptions_1()

    ' Using the raw string array here. See PLINQ Data Sample.
    Dim customers As String() = GetCustomersAsStrings().ToArray()

    ' First, we must simulate some corrupt input.
    customers(20) = "###"

    'throws indexoutofrange
    Dim query = From cust In customers.AsParallel()
                Let fields = cust.Split(","c)
                Where fields(3).StartsWith("C")
                Select fields
    Try
        ' We use ForAll although it doesn't really improve performance
        ' since all output is serialized through the Console.
        query.ForAll(Sub(e)
                         Console.WriteLine("City: {0}, Thread:{1}")
                     End Sub)
    Catch e As AggregateException

        ' In this design, we stop query processing when the exception occurs.
        For Each ex In e.InnerExceptions
            Console.WriteLine(ex.Message)
            If TypeOf ex Is IndexOutOfRangeException Then
                Console.WriteLine("The data source is corrupt. Query stopped.")
            End If
        Next
    End Try
End Sub

Bu örnekte, özel durum oluşturulduktan sonra sorgu devam edemez. Uygulama kodunuz özel durumu yakaladığında PLINQ sorguyu tüm iş parçacıklarında zaten durdurmuş olur.

Örnek 2

Aşağıdaki örnek, bir özel durumu yakalamayı ve sorgu yürütmeye devam etmeyi mümkün kılmak için bir try-catch bloğunun temsilciye nasıl yerleştirebileceğinizi gösterir.

// Paste into PLINQDataSample class.
static void PLINQExceptions_2()
{
    var customers = GetCustomersAsStrings().ToArray();
    // Using the raw string array here.
    // First, we must simulate some corrupt input
    customers[54] = "###";

    // Assume that in this app, we expect malformed data
    // occasionally and by design we just report it and continue.
    static bool IsTrue(string[] f, string c)
    {
        try
        {
            string s = f[3];
            return s.StartsWith(c);
        }
        catch (IndexOutOfRangeException)
        {
            Console.WriteLine($"Malformed cust: {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);
        }
    }
}
' Paste into PLINQDataSample class
Shared Sub PLINQExceptions_2()

    Dim customers() = GetCustomersAsStrings().ToArray()
    ' Using the raw string array here.
    ' First, we must simulate some corrupt input
    customers(20) = "###"

    ' 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.
    Dim isTrue As Func(Of String(), String, Boolean) = Function(f, c)

                                                           Try

                                                               Dim s As String = f(3)
                                                               Return s.StartsWith(c)

                                                           Catch e As IndexOutOfRangeException

                                                               Console.WriteLine("Malformed cust: {0}", f)
                                                               Return False
                                                           End Try
                                                       End Function

    ' Using the raw string array here
    Dim query = From cust In customers.AsParallel()
                Let fields = cust.Split(","c)
                Where isTrue(fields, "C")
                Select New With {.City = fields(3)}
    Try
        ' We use ForAll although it doesn't really improve performance
        ' since all output must be serialized through the Console.
        query.ForAll(Sub(e) Console.WriteLine(e.City))


        ' IndexOutOfRangeException will not bubble up      
        ' because we handle it where it is thrown.
    Catch e As AggregateException
        For Each ex In e.InnerExceptions
            Console.WriteLine(ex.Message)
        Next
    End Try
End Sub

Kod Derleniyor

  • Bu örnekleri derlemek ve çalıştırmak için, bunları PLINQ Veri Örneği örneğine kopyalayın ve Main'dan yöntemini çağırın.

Güçlü Programlama

Programınızın durumunu bozmamak için nasıl işleneceğini bilmiyorsanız bir özel durum yakalamayın.

Ayrıca bkz.