PLinq

https://technet.microsoft.com/zh-cn/library/dd460688(v=vs.100)



处理 PLINQ 查询中的异常

本主题中的第一个示例演示如何处理在 PLINQ 查询执行时可能从中引发的 System.AggregateException 第二个示例演示如何将 try-catch 块放在委托内,尽可能靠近将会引发异常的位置。 通过这种方式,一旦发生异常,您就可以捕获它们并且可能继续执行查询。 如果允许异常向上冒泡回到联接线程,则查询操作也许可以在引发异常后继续处理一些项目。

在某些情况下,当 PLINQ 回退到顺序执行并发生异常时,可能会直接传播该异常,而不是包装到 AggregateException 中。 此外,始终可以直接传播ThreadAbortException

注意注意

当启用“仅我的代码”时,Visual Studio 将在引发异常的行上中断运行,并显示错误消息“异常未由用户代码处理”。此错误是良性的。 可以按 F5 从中断处继续运行,并查看在以下示例中演示的异常处理行为。 若要阻止 Visual Studio 在出现第一个错误时中断运行,只需在“工具”->“选项”->“调试”->“常规”下取消选中“仅我的代码”复选框即可。

本示例旨在演示用法,运行速度可能不如等效的顺序 LINQ to Objects 查询快。 有关加速的更多信息,请参见了解 PLINQ 中的加速

示例

此示例演示如何将 try-catch 块放在执行查询以捕获任何引发的 System.AggregateException 的代码的周围。

C#
VB
// 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.");
        }
    }
}


在此示例中,查询在引发异常后无法继续。 到应用程序代码捕获异常时,PLINQ 已经在所有线程上停止了查询。

下面的示例演示如何将 try-catch 块放在委托中,以便能够捕获异常并继续执行查询。

C#
VB
// 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);
    }
}


你可能感兴趣的:(linq)