From 64c79010953b416de7afdbf4f8d15d613c9e32f7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 29 Jul 2025 21:00:34 +0000 Subject: [PATCH 1/4] Initial plan From 66e15395503769862d3fbd2fd0201a97232c8895 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 29 Jul 2025 21:08:08 +0000 Subject: [PATCH 2/4] Clarify LINQ async example behavior and add contrasting examples Co-authored-by: BillWagner <493969+BillWagner@users.noreply.github.com> --- .../async-scenarios.md | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/csharp/asynchronous-programming/async-scenarios.md b/docs/csharp/asynchronous-programming/async-scenarios.md index 7246ade88a18b..72708fe6c8264 100644 --- a/docs/csharp/asynchronous-programming/async-scenarios.md +++ b/docs/csharp/asynchronous-programming/async-scenarios.md @@ -130,7 +130,25 @@ You can write this code more succinctly by using LINQ: :::code language="csharp" source="snippets/async-scenarios/Program.cs" ID="GetUsersForDatasetByLINQ"::: -Although you write less code by using LINQ, exercise caution when mixing LINQ with asynchronous code. LINQ uses deferred (or lazy) execution. Asynchronous calls don't happen immediately as they do in a `foreach` loop, unless you force the generated sequence to iterate with a call to the `.ToList()` or `.ToArray()` method. This example uses the method to perform the query eagerly and store the results in an array. This approach forces the `id => GetUserAsync(id)` statement to run and initiate the task. +Although you write less code by using LINQ, exercise caution when mixing LINQ with asynchronous code. LINQ uses deferred (or lazy) execution, which means that without immediate evaluation, async calls don't happen until the sequence is enumerated. + +The example above is **correct and safe** because it uses the method to immediately evaluate the LINQ query and store the tasks in an array. This approach ensures the `id => GetUserAsync(id)` calls execute immediately and all tasks start concurrently, just like the `foreach` loop approach. + +**Problematic approach** (without immediate evaluation): +```csharp +// DON'T do this - tasks won't start until enumerated +var getUserTasks = userIds.Select(id => GetUserAsync(id)); // No .ToArray()! +return await Task.WhenAll(getUserTasks); // Tasks start here, not above +``` + +**Recommended approach** (shown in the example above): +```csharp +// DO this - tasks start immediately +var getUserTasks = userIds.Select(id => GetUserAsync(id)).ToArray(); +return await Task.WhenAll(getUserTasks); +``` + +Always use `.ToArray()` or `.ToList()` when creating tasks with LINQ to ensure immediate execution and concurrent task execution. ## Review considerations for asynchronous programming From 7cd9d7892eeb238e2d35508d0e15e00c9fd61ee8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 30 Jul 2025 18:34:46 +0000 Subject: [PATCH 3/4] Fix markdown lint issues: remove trailing spaces and add blank lines around code blocks Co-authored-by: BillWagner <493969+BillWagner@users.noreply.github.com> --- docs/csharp/asynchronous-programming/async-scenarios.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/csharp/asynchronous-programming/async-scenarios.md b/docs/csharp/asynchronous-programming/async-scenarios.md index 72708fe6c8264..0d4e095805016 100644 --- a/docs/csharp/asynchronous-programming/async-scenarios.md +++ b/docs/csharp/asynchronous-programming/async-scenarios.md @@ -130,11 +130,12 @@ You can write this code more succinctly by using LINQ: :::code language="csharp" source="snippets/async-scenarios/Program.cs" ID="GetUsersForDatasetByLINQ"::: -Although you write less code by using LINQ, exercise caution when mixing LINQ with asynchronous code. LINQ uses deferred (or lazy) execution, which means that without immediate evaluation, async calls don't happen until the sequence is enumerated. +Although you write less code by using LINQ, exercise caution when mixing LINQ with asynchronous code. LINQ uses deferred (or lazy) execution, which means that without immediate evaluation, async calls don't happen until the sequence is enumerated. The example above is **correct and safe** because it uses the method to immediately evaluate the LINQ query and store the tasks in an array. This approach ensures the `id => GetUserAsync(id)` calls execute immediately and all tasks start concurrently, just like the `foreach` loop approach. **Problematic approach** (without immediate evaluation): + ```csharp // DON'T do this - tasks won't start until enumerated var getUserTasks = userIds.Select(id => GetUserAsync(id)); // No .ToArray()! @@ -142,6 +143,7 @@ return await Task.WhenAll(getUserTasks); // Tasks start here, not above ``` **Recommended approach** (shown in the example above): + ```csharp // DO this - tasks start immediately var getUserTasks = userIds.Select(id => GetUserAsync(id)).ToArray(); From 4e95dec5ad7632582e3b19c91eb1cc1a8ac62e7b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 5 Aug 2025 19:53:05 +0000 Subject: [PATCH 4/4] Apply reviewer suggestions: fix punctuation and use xrefs for API links Co-authored-by: gewarren <24882762+gewarren@users.noreply.github.com> --- .../asynchronous-programming/async-scenarios.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/csharp/asynchronous-programming/async-scenarios.md b/docs/csharp/asynchronous-programming/async-scenarios.md index 0d4e095805016..e72592944ddfc 100644 --- a/docs/csharp/asynchronous-programming/async-scenarios.md +++ b/docs/csharp/asynchronous-programming/async-scenarios.md @@ -132,25 +132,25 @@ You can write this code more succinctly by using LINQ: Although you write less code by using LINQ, exercise caution when mixing LINQ with asynchronous code. LINQ uses deferred (or lazy) execution, which means that without immediate evaluation, async calls don't happen until the sequence is enumerated. -The example above is **correct and safe** because it uses the method to immediately evaluate the LINQ query and store the tasks in an array. This approach ensures the `id => GetUserAsync(id)` calls execute immediately and all tasks start concurrently, just like the `foreach` loop approach. +The previous example is correct and safe, because it uses the method to immediately evaluate the LINQ query and store the tasks in an array. This approach ensures the `id => GetUserAsync(id)` calls execute immediately and all tasks start concurrently, just like the `foreach` loop approach. **Problematic approach** (without immediate evaluation): ```csharp -// DON'T do this - tasks won't start until enumerated +// DON'T do this - tasks won't start until enumerated. var getUserTasks = userIds.Select(id => GetUserAsync(id)); // No .ToArray()! -return await Task.WhenAll(getUserTasks); // Tasks start here, not above +return await Task.WhenAll(getUserTasks); // Tasks start here. ``` -**Recommended approach** (shown in the example above): +**Recommended approach**: ```csharp -// DO this - tasks start immediately +// DO this - tasks start immediately. var getUserTasks = userIds.Select(id => GetUserAsync(id)).ToArray(); return await Task.WhenAll(getUserTasks); ``` -Always use `.ToArray()` or `.ToList()` when creating tasks with LINQ to ensure immediate execution and concurrent task execution. +Always use or when creating tasks with LINQ to ensure immediate execution and concurrent task execution. ## Review considerations for asynchronous programming