MSDN Magazine - October 2007 - (Page 75) one of them, the exception is thrown immediately and the subsequent elements will not even be considered. The same is not true of PLINQ. As an illustration, take a look at this (contrived) query: object[] data = new object[] { “foo”, null, null, null }; var q = data.Select(x => x.ToString()); foreach (var e in q) Console.WriteLine(e); today. Thankfully, PLINQ preserves the original stack traces, so if you expand the MultipleFailuresException object and look at its InnerExceptions property, you will find the full set of exceptions with the complete original stack traces available. Ordering in the Output Results Say you’ve written the following code in LINQ: int[] data = new int[] { 0, 1, 2, 3 }; int[] data2 = (from x in data select x * 2).ToArray(); Every time you run it with LINQ, it will succeed in running ToString on the first array element, and then it will fail with a NullReferenceException trying to call ToString on the second. You never get to the third or fourth element. When multiple processors are involved, however, as is the case with PLINQ, you have the possibility that multiple exceptions can happen in parallel. Depending on how PLINQ decides to subdivide the problem, you may see failures for 1, 2, and 3, all simultaneously, or any combination of those, including possibly 3, but not 1 or 2. To deal with this, PLINQ uses a slightly different exception model than LINQ to communicate failures. When an exception occurs on one of the PLINQ threads, the system first tries to stop all other threads from running as quickly as possible. This process happens completely transparently. But this may or may not be accomplished in time to prevent other exceptions from happening concurrently and, indeed, they may have already occurred by the time PLINQ gets involved. Once all threads have shut down, the full set of exceptions that have occurred will be aggregated into a new System.Concurrency.MultipleFailuresException object and that new aggregate exception object will be rethrown. Each exception that occurred is subsequently accessible through the InnerExceptions property, of type Exception[], including unperturbed stack traces. PLINQ actually always throws a single MultipleFailuresException when an unhandled exception terminates a query’s execution, even if only one exception is actually thrown. In the previous example, that means PLINQ always wraps the NullReferenceExceptions in a MultipleFailuresException. If it didn’t and you wanted to catch an exception of a particular type, you’d have to write multiple catch clauses. Clearly you usually don’t catch certain kinds of exceptions, but if you had wanted to, you would have had to write the following and duplicate a bunch of logic: try { // query } catch (NullReferenceException) { } catch (MultipleFailuresException) { } Can you predict the contents of data2? The question seems so simple that it’s silly to even consider. Everybody would say: { 0, 2, 4, 6 }. But if you just change the code as shown here, the possible contents of data2 actually differs: int[] data = new int[] { 0, 1, 2, 3 }; int[] data2 = (from x in data.AsParallel() select x * 2).ToArray(); In this case, { 0, 2, 4, 6 } is surely possible, but so is { 6, 0, 2, 4 }, or any other permutation of these four numbers. This is so because PLINQ runs the query in parallel and the results are made available as soon as they become available, no matter whether you are iterating over the query with foreach or marshaling the results into an array with ToArray. The LINQ ordering is simply a byproduct of the fact that its implementation processes input sequentially. Conversely, the PLINQ ordering is determined by the nondeterministic scheduling of parallel units of work, which is apt to change wildly from one execution to the next. This was an explicit design decision made by the PLINQ team. Historically, queries have not guaranteed anything about ordering. If you take a look at SQL Server™, for example, unless you have specified an order by clause in the query text, the ordering will be dependent on many things: whether an index is used in the query, the layout of records on disk, and so on. In fact, it can also be nondeterministic, because SQL Server can use parallelism in the evaluation of queries too! Because users frequently need to preserve ordering, and to alleviate some minor challenges for some people trying to migrate from LINQ, PLINQ offers a way of opting in to order preservation. Order preservation simply ensures that, provided there are no intervening sort operations, the relative ordering among output elements is strongly tied to the relative ordering among input elements. If you wanted to ensure that the output of the above query was always {0, 2, 4, 6 }, then you can use the following query instead: int[] data = new int[] { 0, 1, 2, 3 }; int[] data2 = (from x in data.AsParallel(QueryOptions.PreserveOrdering) select x * 2).ToArray(); Not only is this clumsy, but developers would be apt to forget about one or the other, leading to bugs that happen only under some circumstances and configurations. This can unfortunately make debugging more difficult. If an exception goes unhandled and you attach a debugger, you will break into the call to GetEnumerator (if you’re calling foreach over the query results) rather than where your exception originated from to begin with. This is similar to what occurs with the asynchronous programming model (BeginXX/EndXX) in the .NET Framework Order preservation is not free. In fact, it can substantially impact the performance and scaling of your queries. This is because PLINQ will logically insert a sort operation at the end, and the sort is an operator that does not scale perfectly with an increase in the number of processors. To get an idea of what this means, the previous query is logically equivalent to the following query: int[] data = new int[] { 0, 1, 2, 3 }; int[] data2 = data.AsParallel(). Select((x, i) => new { x, i }). // remember indices Select((x) => new { x * 2, i }). // (in original) OrderBy((x) => x.i). // ensure order is preserved Select((x) => x.x). // get rid of indices from output ToArray(); // (in original) PlINQ october2007 75
Table of Contents Feed for the Digital Edition of MSDN Magazine - October 2007 Cover Contents Toolbox CLR Inside Out Basic Instincts Data Points Cutting Edge Pooled Threads WPF Threads Parallel Linq Parallel Performance Mobile Apps Test Run Foundations Windows with C++ Netting C++ .NET Matters { End Bracket } Net Nuptials MSDN Magazine - October 2007 MSDN Magazine - October 2007 - Contents (Page Cover1) MSDN Magazine - October 2007 - Contents (Page Cover2) MSDN Magazine - October 2007 - Contents (Page 1) MSDN Magazine - October 2007 - Contents (Page 2) MSDN Magazine - October 2007 - Contents (Page 3) MSDN Magazine - October 2007 - Contents (Page 4) MSDN Magazine - October 2007 - Contents (Page 5) MSDN Magazine - October 2007 - Contents (Page 6) MSDN Magazine - October 2007 - Contents (Page 7) MSDN Magazine - October 2007 - Contents (Page 8) MSDN Magazine - October 2007 - Contents (Page 9) MSDN Magazine - October 2007 - Contents (Page 10) MSDN Magazine - October 2007 - Toolbox (Page 11) MSDN Magazine - October 2007 - Toolbox (Page 12) MSDN Magazine - October 2007 - Toolbox (Page 13) MSDN Magazine - October 2007 - Toolbox (Page 14) MSDN Magazine - October 2007 - Toolbox (Page 15) MSDN Magazine - October 2007 - Toolbox (Page 16) MSDN Magazine - October 2007 - CLR Inside Out (Page 17) MSDN Magazine - October 2007 - CLR Inside Out (Page 18) MSDN Magazine - October 2007 - CLR Inside Out (Page 19) MSDN Magazine - October 2007 - CLR Inside Out (Page 20) MSDN Magazine - October 2007 - CLR Inside Out (Page 21) MSDN Magazine - October 2007 - CLR Inside Out (Page 22) MSDN Magazine - October 2007 - CLR Inside Out (Page 23) MSDN Magazine - October 2007 - CLR Inside Out (Page 24) MSDN Magazine - October 2007 - CLR Inside Out (Page 25) MSDN Magazine - October 2007 - CLR Inside Out (Page 26) MSDN Magazine - October 2007 - CLR Inside Out (Page 27) MSDN Magazine - October 2007 - CLR Inside Out (Page 28) MSDN Magazine - October 2007 - CLR Inside Out (Page 29) MSDN Magazine - October 2007 - CLR Inside Out (Page 30) MSDN Magazine - October 2007 - Basic Instincts (Page 31) MSDN Magazine - October 2007 - Basic Instincts (Page 32) MSDN Magazine - October 2007 - Basic Instincts (Page 33) MSDN Magazine - October 2007 - Basic Instincts (Page 34) MSDN Magazine - October 2007 - Basic Instincts (Page 35) MSDN Magazine - October 2007 - Basic Instincts (Page 36) MSDN Magazine - October 2007 - Data Points (Page 37) MSDN Magazine - October 2007 - Data Points (Page 38) MSDN Magazine - October 2007 - Data Points (Page 39) MSDN Magazine - October 2007 - Data Points (Page 40) MSDN Magazine - October 2007 - Data Points (Page 41) MSDN Magazine - October 2007 - Data Points (Page 42) MSDN Magazine - October 2007 - Cutting Edge (Page 43) MSDN Magazine - October 2007 - Cutting Edge (Page 44) MSDN Magazine - October 2007 - Cutting Edge (Page 45) MSDN Magazine - October 2007 - Cutting Edge (Page 46) MSDN Magazine - October 2007 - Cutting Edge (Page 47) MSDN Magazine - October 2007 - Cutting Edge (Page 48) MSDN Magazine - October 2007 - Cutting Edge (Page 49) MSDN Magazine - October 2007 - Cutting Edge (Page 50) MSDN Magazine - October 2007 - Cutting Edge (Page 51) MSDN Magazine - October 2007 - Cutting Edge (Page 52) MSDN Magazine - October 2007 - Cutting Edge (Page 53) MSDN Magazine - October 2007 - Pooled Threads (Page 54) MSDN Magazine - October 2007 - Pooled Threads (Page 55) MSDN Magazine - October 2007 - Pooled Threads (Page 56) MSDN Magazine - October 2007 - Pooled Threads (Page 57) MSDN Magazine - October 2007 - Pooled Threads (Page 58) MSDN Magazine - October 2007 - Pooled Threads (Page 59) MSDN Magazine - October 2007 - Pooled Threads (Page 60) MSDN Magazine - October 2007 - Pooled Threads (Page 61) MSDN Magazine - October 2007 - Pooled Threads (Page 62) MSDN Magazine - October 2007 - Pooled Threads (Page 63) MSDN Magazine - October 2007 - Pooled Threads (Page 64) MSDN Magazine - October 2007 - Pooled Threads (Page 65) MSDN Magazine - October 2007 - WPF Threads (Page 66) MSDN Magazine - October 2007 - WPF Threads (Page 67) MSDN Magazine - October 2007 - WPF Threads (Page 68) MSDN Magazine - October 2007 - WPF Threads (Page 69) MSDN Magazine - October 2007 - Parallel Linq (Page 70) MSDN Magazine - October 2007 - Parallel Linq (Page 71) MSDN Magazine - October 2007 - Parallel Linq (Page 72) MSDN Magazine - October 2007 - Parallel Linq (Page 73) MSDN Magazine - October 2007 - Parallel Linq (Page 74) MSDN Magazine - October 2007 - Parallel Linq (Page 75) MSDN Magazine - October 2007 - Parallel Linq (Page 76) MSDN Magazine - October 2007 - Parallel Linq (Page 77) MSDN Magazine - October 2007 - Parallel Linq (Page 78) MSDN Magazine - October 2007 - Parallel Performance (Page 79) MSDN Magazine - October 2007 - Parallel Performance (Page 80) MSDN Magazine - October 2007 - Parallel Performance (Page 81) MSDN Magazine - October 2007 - Parallel Performance (Page 82) MSDN Magazine - October 2007 - Parallel Performance (Page 83) MSDN Magazine - October 2007 - Parallel Performance (Page 84) MSDN Magazine - October 2007 - Parallel Performance (Page 85) MSDN Magazine - October 2007 - Parallel Performance (Page 86) MSDN Magazine - October 2007 - Parallel Performance (Page 87) MSDN Magazine - October 2007 - Parallel Performance (Page 88) MSDN Magazine - October 2007 - Parallel Performance (Page 89) MSDN Magazine - October 2007 - Parallel Performance (Page 90) MSDN Magazine - October 2007 - Mobile Apps (Page 91) MSDN Magazine - October 2007 - Mobile Apps (Page 92) MSDN Magazine - October 2007 - Mobile Apps (Page 93) MSDN Magazine - October 2007 - Mobile Apps (Page 94) MSDN Magazine - October 2007 - Mobile Apps (Page 95) MSDN Magazine - October 2007 - Mobile Apps (Page 96) MSDN Magazine - October 2007 - Mobile Apps (Page 97) MSDN Magazine - October 2007 - Mobile Apps (Page 98) MSDN Magazine - October 2007 - Mobile Apps (Page 99) MSDN Magazine - October 2007 - Mobile Apps (Page 100) MSDN Magazine - October 2007 - Test Run (Page 101) MSDN Magazine - October 2007 - Test Run (Page 102) MSDN Magazine - October 2007 - Test Run (Page 103) MSDN Magazine - October 2007 - Test Run (Page 104) MSDN Magazine - October 2007 - Test Run (Page 105) MSDN Magazine - October 2007 - Test Run (Page 106) MSDN Magazine - October 2007 - Test Run (Page 107) MSDN Magazine - October 2007 - Test Run (Page 108) MSDN Magazine - October 2007 - Test Run (Page 109) MSDN Magazine - October 2007 - Test Run (Page 110) MSDN Magazine - October 2007 - Test Run (Page 111) MSDN Magazine - October 2007 - Test Run (Page 112) MSDN Magazine - October 2007 - Test Run (Page 113) MSDN Magazine - October 2007 - Test Run (Page 114) MSDN Magazine - October 2007 - Foundations (Page 115) MSDN Magazine - October 2007 - Foundations (Page 116) MSDN Magazine - October 2007 - Foundations (Page 117) MSDN Magazine - October 2007 - Foundations (Page 118) MSDN Magazine - October 2007 - Foundations (Page 119) MSDN Magazine - October 2007 - Foundations (Page 120) MSDN Magazine - October 2007 - Foundations (Page 121) MSDN Magazine - October 2007 - Foundations (Page 122) MSDN Magazine - October 2007 - Foundations (Page 123) MSDN Magazine - October 2007 - Foundations (Page 124) MSDN Magazine - October 2007 - Windows with C++ (Page 125) MSDN Magazine - October 2007 - Windows with C++ (Page 126) MSDN Magazine - October 2007 - Windows with C++ (Page 127) MSDN Magazine - October 2007 - Windows with C++ (Page 128) MSDN Magazine - October 2007 - Windows with C++ (Page 129) MSDN Magazine - October 2007 - Windows with C++ (Page 130) MSDN Magazine - October 2007 - Windows with C++ (Page 131) MSDN Magazine - October 2007 - Windows with C++ (Page 132) MSDN Magazine - October 2007 - Netting C++ (Page 133) MSDN Magazine - October 2007 - Netting C++ (Page 134) MSDN Magazine - October 2007 - Netting C++ (Page 135) MSDN Magazine - October 2007 - Netting C++ (Page 136) MSDN Magazine - October 2007 - .NET Matters (Page 137) MSDN Magazine - October 2007 - .NET Matters (Page 138) MSDN Magazine - October 2007 - .NET Matters (Page 139) MSDN Magazine - October 2007 - .NET Matters (Page 140) MSDN Magazine - October 2007 - .NET Matters (Page 141) MSDN Magazine - October 2007 - .NET Matters (Page 142) MSDN Magazine - October 2007 - .NET Matters (Page 143) MSDN Magazine - October 2007 - Net Nuptials (Page 144) MSDN Magazine - October 2007 - Net Nuptials (Page Cover3) MSDN Magazine - October 2007 - Net Nuptials (Page Cover4)
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.