Stop Using .ForEach with await! Here’s the Right Way in C# 💻

แชร์
ฝัง
  • เผยแพร่เมื่อ 2 ก.พ. 2025

ความคิดเห็น • 22

  • @Elias-ib1qt
    @Elias-ib1qt 4 หลายเดือนก่อน +20

    Why not use .Select and Task.WaitAll?

  • @eugenpaval
    @eugenpaval 4 หลายเดือนก่อน +3

    There’s no need to use Parallel class for asynchronous calls. Instead don’t await on individual tasks, rather do a WhenAll or WhenAny as others have pointed it out. Or with net 9 there is a WhenEach variant allowing asynchronous await on all the tasks in any order they complete. The reason for not using Parallel class is due to the implementation difference between
    I/O bound and CPU bound threads. Asynchronous operations are implemented via a thread pool taking into account the fact the COU is mostly unused for the duration of the call. CPU bound work is done on parallel threads mapped directly to the logical CPU cores.

  • @veniaminbalan
    @veniaminbalan 4 หลายเดือนก่อน +2

    i encountered this problem exactly when you posted this video, thanks very much !!!

    • @dosovi4548bustayes
      @dosovi4548bustayes 4 หลายเดือนก่อน +1

      you are very lucky bro... chat gpt learned from this guy hahaha

  • @orterves
    @orterves 4 หลายเดือนก่อน +5

    I can count on one hand the times I have used List.ForEach in C# and I've used it for more than 10 years.
    Your example "fetchFromDatabase" would in practice be written by passing the list of ids in and batch requesting .where(contains) (or whatever db fetch strategy is optimal), which gives you the option of using IAsyncEnumerable, the way it's written you're making N calls to the database

    • @okharev8114
      @okharev8114 4 หลายเดือนก่อน

      i use it quite extensively for I/O workloads (files downloads in parrallel) it's actually really useful to avoid boilerplate

  • @jonasgranlund4427
    @jonasgranlund4427 4 หลายเดือนก่อน +1

    Great content as always.

  • @padnom4991
    @padnom4991 4 หลายเดือนก่อน +2

    Thx a lot for your video ,
    Can you use parallel if you call a repository with a dbcontext ?

    • @Riketta
      @Riketta 4 หลายเดือนก่อน +1

      If you have DB requests in a loop then you are doing something wrong in your life.
      Otherwise it is "parallel" by itself due to different task from different clients will be scheduled on different threads due to thread pool.

    • @Udodisgustme
      @Udodisgustme 4 หลายเดือนก่อน

      You can for multi reads. For multi writes also but make sure its under transaction scope

    • @zagoskintoto
      @zagoskintoto 4 หลายเดือนก่อน +1

      DbContext is not thread safe so you'd need to instantiate a new context for each operation.

    • @padnom4991
      @padnom4991 4 หลายเดือนก่อน

      @@Riketta "So, making database requests in a loop means you're 'doing something wrong in your life'? What kind of dumb comment is that? I asked this question on purpose because not all tasks can be efficiently parallelized, especially with a DbContext that isn’t thread-safe. Forcing a Parallel.ForEach where it doesn’t apply can cause more issues than it solves. And just to remind you, this video is aimed at beginners. You could have just pointed out that for read operations, it's possible to parallelize if you're accessing different tables or if you're registering the DbContext as transient, instead of jumping to useless judgments.

    • @Riketta
      @Riketta 4 หลายเดือนก่อน

      ​@@padnom4991 you are right, if in your reality loops more often than almost never used to complete actions like "accessing different tables".

  • @WeirdoPlays
    @WeirdoPlays 4 หลายเดือนก่อน

    what if we want to send multiple HttpClient requests

  • @kevman2296
    @kevman2296 4 หลายเดือนก่อน +1

    Could you create a video about using Radzen within MAUI Blazor?

  • @zagoskintoto
    @zagoskintoto 4 หลายเดือนก่อน

    You should probably be using ConcurrentBag for your last example. I know it's a bit out of scope but just be correct. Other than that, great video!

  • @dasfahrer8187
    @dasfahrer8187 4 หลายเดือนก่อน

    You should be able to do a WhenAll and Select, then an OrderBy on the whole thing. Something like this:
    var numbers = new List { 1, 2, 3, 4 };
    (await Task.WhenAll(numbers.Select(async (n, index) =>
    {
    await Task.Delay(250);
    return new { Index = index, Value = n };
    })))
    .OrderBy(result => result.Index)
    .ToList()
    .ForEach(result => Console.WriteLine(result.Value));

  • @temp50
    @temp50 หลายเดือนก่อน

    But why would anyone do that? void Action ... signature does no equal to Task Action. List.ForeEach was never meant to be (ab)used with "void async" signature of anonymous lamda actions.

  • @thotchs4116
    @thotchs4116 4 หลายเดือนก่อน

    gj patrick

  • @knightmarerip711
    @knightmarerip711 4 หลายเดือนก่อน

    Sorry, but I do not think you are comparing the same thing. The reason the list.foreach(async...) code did not return anything is because the program terminated right away. If you add a console.ReadLine() at the end, this will allow the tasks created in the loop to do their thing and should display the results.

    • @temp50
      @temp50 หลายเดือนก่อน

      list.foreach(async...) Doesn't have to 'return' anything. It should write to the console.