The Coolest Way To Await Multiple Tasks in .NET

  Рет қаралды 62,048

Nick Chapsas

Nick Chapsas

7 ай бұрын

Use code EF20 and get 20% off the brand new "Entity Framework Core in .NET" course on Dometrain: dometrain.com/course/from-zer...
Use code GRPC20 and get 20% off the brand new "gRPC in .NET" course on Dometrain: dometrain.com/course/from-zer...
Get the source code: mailchi.mp/dometrain/jo8rclczcz
Become a Patreon and get special perks: / nickchapsas
Hello everybody, I'm Nick, and in this video, I'll show you what I think is the coolest way to await multiple tasks in C#. We won't simply use Task.WhenAll but rather introduce a pretty advanced technique to wrap it into a nice developer experience.
Workshops: bit.ly/nickworkshops
Don't forget to comment, like and subscribe :)
Social Media:
Follow me on GitHub: github.com/Elfocrash
Follow me on Twitter: / nickchapsas
Connect on LinkedIn: / nick-chapsas
Keep coding merch: keepcoding.shop
#csharp #dotnet

Пікірлер: 186
@jkdmyrs
@jkdmyrs 7 ай бұрын
Really glossed over the “TaskExt” and why you shouldn’t use “Task.WhenAll”. Can you expand on this?
@eddypartey1075
@eddypartey1075 7 ай бұрын
Task.WhenAll returns only one exception even if several exceptions have happened
@ChristianWengel
@ChristianWengel 7 ай бұрын
This is because when awaiting the task returned by Task.WhenAll in a try-catch block, the exception caught will be the first inner exception of the AggregateException of that task. This means that other exceptions that may have occurred are swallowed.
@nofatchicks6
@nofatchicks6 7 ай бұрын
This was presumably intentional. He wants you to sign up to his mailing list to get the source code for TaskExt
@parlor3115
@parlor3115 7 ай бұрын
He did a video on it already
@Tullo_x86
@Tullo_x86 7 ай бұрын
Might have been handy to mention which video it was covered in 🤷🏼
@Misteribel
@Misteribel 7 ай бұрын
The actual issue with this approach is that 'await' is normally deliberately preventing parallel execution, and 'WhenAll' clearly conveys the opposite intention. If the awaiter extension would await in sequence (like in a for loop with await), it would be closer to a Principle of Least Surprise, the code would still be easy to understand. Be careful with automatic parallelization, people rarely write proper parallizable code, not even when asked.
@thedreadedgman
@thedreadedgman 7 ай бұрын
I was going to write something like this... I think it's better to have the WhenAll there so you can tell what's happening... I didn't understand why we want to abstract the WhenAll into "Magic"
@qj0n
@qj0n 7 ай бұрын
I personally think it's a good idea to simplify parallelism of tasks, but yes - not to this extent maybe. Like it'd be nice to have some .AsParallelTask() extension method for the tuple and this way is still quite easy, but it's clear it runs in parallel
@gliaMe
@gliaMe 7 ай бұрын
With the await outside the parantheses I would not expect the tasks inside the parantheses to be executed sequentially. Exactly how it works. The issue I have with this is, that developers not knowing the extension would have a hard time finding out what is going on.
@Misteribel
@Misteribel 7 ай бұрын
@gliaMe good point, but if you ever used await in the collection of a for loop (ie, IAsyncEnumerable), you would know that the whole collection is awaited item by item, sequentially. If the BCL has that as the default, deviating from how a collection is typically awaited, is gonna lead to surprises. Plus, it requires *everyone* who uses this construct to write parallizable code, not just the ones who "get it". And we all know how easy it is to get that wrong.
@fatman_slim5
@fatman_slim5 7 ай бұрын
Yeah, I keep seeing people trying to treat async tasks as parallel by invoking multiple async methods and awaiting them with a WhenAll... You can get some very unexpected behavior...
@Light_Akira
@Light_Akira 7 ай бұрын
yes, we need more obfuscated code! anyway, nice trick, but i would use it if it would be a part of the standard library, only.
@DemoBytom
@DemoBytom 7 ай бұрын
It should be easy to write a code generator, that would scan the code for any combination of code written that awaits a tuple of some Tasks, and generate apropriate extension methods, including a type that awaits tasks of different T-s.
@asedtf
@asedtf 7 ай бұрын
Or just write the extension methods once. Especially easy with tools like Copilot
@qj0n
@qj0n 7 ай бұрын
⁠fine if you use only task. Combine generic and non-generics, tasks, valuetasks and maybe other awaitable and you green hundreds of methods
@Shadow_Play3r
@Shadow_Play3r 7 ай бұрын
oh definitely cool way to destruct at the end. I wonder what are your thoughts if we want to group tasks of different return types. Like two different types, i think then the task.whenall doesnt support a unified array return; but we can certainly have our own implementation to work with it
@benjamininkorea7016
@benjamininkorea7016 7 ай бұрын
Super cool walk through this method, and will definitely add a neat tool to my repertoire, but I have to confess I'd be unlikely to use it: if I come back to this code a year from now, I'd have to investigate "Hmmmm. . . what was I up to with this line of code?" With the vanilla form, I'd know just from experience.
@gozieene8880
@gozieene8880 7 ай бұрын
Exactly
@RealDieselMeister
@RealDieselMeister 7 ай бұрын
Please don't for the sake of your colleagues and the people, who have to maintain your code later. Please don't do it. Be explicit on what's happen there.
@MetalKid007
@MetalKid007 7 ай бұрын
Personally, it would be more useful if you could mix types as its petty rare that you would call the same method in parallel with different parameters so close together.
@MarkRendle
@MarkRendle 7 ай бұрын
That would just be something like public static TaskAwaiter GetAwaiter(this (Task, Task) tasksTuple)
@MarkRendle
@MarkRendle 7 ай бұрын
This, in fact: public static class TaskTupleExtensions { public static async Task Foo() { var (a, b) = await (Task.FromResult("A"), Task.FromResult("B")); } public static TaskAwaiter GetAwaiter(this (Task, Task) tuple) { return Combine(tuple.Item1, tuple.Item2).GetAwaiter(); } private static async Task Combine(Task task1, Task task2) { await Task.WhenAll(task1, task2); return (task1.Result, task2.Result); } }
@JochenZeischka
@JochenZeischka 7 ай бұрын
This is a very common scenario indeed and it doesn't require any "special code" to me: Task getInteger = GetIntegerAsync(); Task getString = GetStringAsync(); int i = await getInteger; string s = await getString;
@dangerfox1776
@dangerfox1776 7 ай бұрын
This sounds like a narrow view on your workflows only. For instance I can fire off 170 TCP connection requests that pull state data from physical devices as part of my init of an automation program. I want those connections to happen simultaneously and not freeze the UI, plus let me know when they've all completed / timed out.
@qj0n
@qj0n 7 ай бұрын
@@dangerfox1776if you run 170 tasks, you probably want to run them in a loop or linq, not using tuple with 170 items... I think existing task methods are perfectly fine
@casperhansen826
@casperhansen826 7 ай бұрын
I am not sure that I have ever encountered a situation where this was needed, but you never know, thanks for some hints
@davidchen8786
@davidchen8786 6 ай бұрын
I tried this using Dictionary instead and it's amazing. Thanks Nick love your examples, keep up the good work..
@unseenexception
@unseenexception 7 ай бұрын
Discovered this gem in the UniTask library! So cool!
@nove1398
@nove1398 7 ай бұрын
This is pretty neat, I can find use for this approach, and the source code for EXT you provided is great! Definitely will be applying the pattern in my project
@RealDieselMeister
@RealDieselMeister 7 ай бұрын
Please don't for the sake of your colleagues and the people, who have to maintain your code later. Please don't do it. Be explicit on what's happen there.
@soverain
@soverain 7 ай бұрын
I really like this kind of quality of life improvements. Especially the one with tuple destructuring!
@fedefex1
@fedefex1 7 ай бұрын
Great video as always! Can I ask you where did you find this technique?
@damiank6566
@damiank6566 7 ай бұрын
@Nick, Could you elaborate more about the exception handling in Task.WhenAll()? I recently had a situation like that and I'm curious about your thoughts and potential traps: var tasks = someList.Select(async x => await DoSomethingAsync()); Task.WhenAll(tasks); worth to mention that DoSomethingAsync contains try-catch where catch is just basically writing a log message. //not sure if I got that right, I'm writing from a memory couple weeks back, but you get the idea
@chriskruining
@chriskruining 7 ай бұрын
I think it is even worth to write a source generator for this. That said I am unsure about this, because you are pretty much only adding some syntax sugar on Task.WhenAll (or whatever implementation you decide to user). Wherein lies my uncertainty; you are hiding the implementation. I think this technique fits in the same category as operator overloading: really powerful, but you remove how many assumptions can be made about a piece of code. And I cannot overstate the importance and power that assumptions bring to code, especially when working in a team. Then again, operator overloads change existing behavior, whilst this adds new behavior where there was non. I will discuss this with my colleagues for sure
@RealDieselMeister
@RealDieselMeister 7 ай бұрын
XD I like, when the source generator become the "hammer" from the saying "if you have only a hammer, everything is a nail!" XD
@jewersp
@jewersp 7 ай бұрын
@@RealDieselMeisterWell, here it actually makes sense, because otherwise you'll need a long list of overloads to accomodate the amount of tasks that should run in parallel. A source generator could just generate the required overload for you.
@path_selector
@path_selector 7 ай бұрын
seriously surprised how clean this code is. I love it and will definitely implement
@path_selector
@path_selector 7 ай бұрын
where can i find TaskExt?? do i need to be a patreon member…
@nickchapsas
@nickchapsas 7 ай бұрын
No you don't. Check the description.
@TreyMack
@TreyMack 7 ай бұрын
Love everything else on your channel!
@Schnickalodeon
@Schnickalodeon 6 ай бұрын
Could you do a video regarding some concurrent queue techniques in C#. That would be awesome :)
7 ай бұрын
A nice way of confusing the next person that reads your code (including your future you), for the only sake of being cool. Just picture a reader that doesn't know about this language feature.
@pilotboba
@pilotboba 7 ай бұрын
can you use params in the extension method? Rather than creating a bunch of overloads?
@richardaubin1951
@richardaubin1951 7 ай бұрын
What would using an IEnumerable as the parameter look like?
@jtucker87
@jtucker87 7 ай бұрын
Just added this to my works Toolbox Nuget. But I made it so that the types of each Tuple didn't need to match. Thanks!
@itech-planetcomputers9422
@itech-planetcomputers9422 7 ай бұрын
Thanks Nick. I am thinking what if I have IEnumerable of Task. Will try it and see. Cheers!!!
@conradpetrich5093
@conradpetrich5093 7 ай бұрын
@nickchapsas Have you ever made a generic Await extension method to chain sync methods with async methods? Instead of `var result = (await doSomethingAsync()).Select(item => item.Property);` you do something like this: `var result = doSomethingAsync().Await().Select(item => item.Property);` What are the draws and drawbacks to having this type of functionality?
@Lactorioga
@Lactorioga 7 ай бұрын
Looks like proposal for C# 13 !
@LeonWaidyarathna
@LeonWaidyarathna 7 ай бұрын
Thanks it's helps me to improve my code
@flybyw
@flybyw 7 ай бұрын
Since the tasks are already started when passed into the extension method, wouldn't it be more performant to just await both in sequence and avoid the array allocation?
@Grimlock1979
@Grimlock1979 7 ай бұрын
Avoiding an array allocation is good, but Task.WhenAll has the benefit of catching all exceptions that may be thrown in subtasks.
@GigAHerZ64
@GigAHerZ64 7 ай бұрын
If the task return type is same for all, i would expect an array of tasks as "input" instead of a tuple. i could do something like: var weathers = await new[]{ GetWeather("London"), GetWeather("Paris") }; In case of tuples, it would be a valid assumption that the return types are different. And when it wouldn't work as i would assume then, i would be frustrated by this code quite a bit...
@monydragon
@monydragon 7 ай бұрын
So i was thinking, wouldn't it be possible to use the parms type parameter so you can dynamically add as many tasks as needed? I could be wrong but is that possible?
@_tonypacheco
@_tonypacheco 7 ай бұрын
There's an overload for Task.WhenAll that accepts an IEnumerable so it should work 🤔 have to try it out
@GianniKoch
@GianniKoch 7 ай бұрын
Does the EF course on dometrain also contains a chapter of how to deal with multiple client applications using the same database and how to not mess up with tracking and overwriting entities?
@sevensolutions77
@sevensolutions77 7 ай бұрын
I fully agree with the teaser image title 😂
@prman9984
@prman9984 7 ай бұрын
You can just say: var london = service.GetWeather("london"); var paris = service.GetWeather("paris"); var londonWeather = await london; var parisWeather = await paris; That's it. Really simple. No WaitAlls necessary.
@nickchapsas
@nickchapsas 7 ай бұрын
So 4 lines instead of 1?
@JochenZeischka
@JochenZeischka 7 ай бұрын
I’ve been doing this for years and see surprised colleagues every time they see this. Plain easy.
@JochenZeischka
@JochenZeischka 7 ай бұрын
@@nickchapsas unfair comment if you ask me, you still need to deconstruct your tuple. This becomes one long, more difficult line of code to read.
@protox4
@protox4 7 ай бұрын
The problem with this approach is, if the tasks are faulted, you lose the exception info from the second awaited task.
@JochenZeischka
@JochenZeischka 7 ай бұрын
@@protox4 you can throw in a Task.WhenAll() in the middle, without using the result of that (if you feel you need that 2nd exception...)
@Rein______
@Rein______ 7 ай бұрын
Always the same. Some people like crazy fancy code "WhY nOT, tHis Is SO cOOl!1!", others are conservative and like to keep it simple...
@keyser456
@keyser456 7 ай бұрын
Not so much conservative as pragmatic. In the real world these are wasted keystrokes and wasted time.
@tedchirvasiu
@tedchirvasiu 7 ай бұрын
@@keyser456 If you write 100 of these every day, which nobody does. Also, IDEs have suggestions and autocomplete, so writing Task.WhenAll takes maybe a few milliseconds more than opening and closing the parenthesis.
@keyser456
@keyser456 7 ай бұрын
@@tedchirvasiu The point is you can use Task.WhenAll anywhere in any application, and not have to go write this extra ceremony for every situation and combination of parameter numbers and types. The pattern that's trying to be solved is kind of like the "params" scenario where it can take any number, but we're not achieving that. To have to code for each param # variation is just silly and has that code smell. Now we need 3, okay add another extension. Now we need 4, okay add another extension. Now we need... no... bad pattern.
@tedchirvasiu
@tedchirvasiu 7 ай бұрын
@@keyser456 I thought you were saying that using the parens syntax in the video saves you keystrokes compared to writing Task.WhenAll.
@keyser456
@keyser456 7 ай бұрын
@@tedchirvasiu Ah, I get what you mean now. Yeah, reading my post again, I wasn't clear. I think we're in agreement. :)
@sarcasticMoose
@sarcasticMoose 7 ай бұрын
I didn't get the idea. It looks like sytax sugar, there is any reason to await async operations in this specific way?
@KasperDahlTangen
@KasperDahlTangen 7 ай бұрын
Would be clean with TaskAwaiter as return type for tuples. And TaskAwaiter as a return type for arrays, especially in .NET 8 where it is more ergonomic to create collections
@ztBlackGad
@ztBlackGad 7 ай бұрын
It is better to use IEnumerable which constructs using linq :) and then use custom awaiter for enumeration. So syntax will be more relayable.
@chswin
@chswin 7 ай бұрын
That was good one
@gordug
@gordug 7 ай бұрын
Can you create an nth overload which calls back on it's self to support larger numbers of calls?
@lordmetzgermeister
@lordmetzgermeister 7 ай бұрын
Tuples can have 8 items max, so for n items you would just use the base Task.WhenAll anyway. Tuples are rather a syntactic sugar here. By the way, in a real world scenario at that point you might start running into limits of whatever the awaited tasks are doing (db or 3rd party webAPI calls) and you might want to look into limiting the degree of parallelism.
@krccmsitp2884
@krccmsitp2884 7 ай бұрын
Nice!
7 ай бұрын
This is so cool. Thanks for sharing!
@thomasersosi4595
@thomasersosi4595 7 ай бұрын
I'm curious, wouldn't it also work to first create all the tasks and then await them all. Like var taskParis = service.GetWeather("Paris"); var taskLondon = service.GetWeather("London"); var paris = await taskParis; var london = await taskLondon; Or is there a Problem with this approach? What does `WhenAll()` do that this code doesn't?
@nikolajloftjrgensen4629
@nikolajloftjrgensen4629 7 ай бұрын
It will do the same, as if you had await directly on the task line (hence "await service."). So instead of spending 2 x 2 secs, with WhenAll both is running in parallel - and will return when both finishes (and in this case, would result in around 1 x 2 seconds). Using await, won't return before the specific task has finished.
@SerhiiZhydel
@SerhiiZhydel 7 ай бұрын
To me it doen't look that useful. Same thing that Task.WhenAll does but with wrappers that don't add up and don't simplify anything. If I'd see this code somewhere in the project, I'd rather be confused and after spending some time trying to understand what is in there I'd also becode dissapointed that there is nothing but simple await under the hood and as result I'd ask to replace that code with simple Task.WhenAll cause everybody understands that instantly.
@zzing
@zzing 7 ай бұрын
Can you use ConfigureAwait with this?
@clhoover4
@clhoover4 7 ай бұрын
I really like your channel but the promotions are getting crazy. On this subject, tuples are very powerful, use in switch (pattern matching), assignment, operator, etc... This is a good idea but I am always thinking about the reading/understanding part of what the program communicates with other developers. I have a "Option" and "Option" that are used to pass around state and payload for flow, return, logging, etc... control. The library has a design rule to only throw exception when there really is a volition such as unreachable code or unknown type. This pattern has really made the logic flow much easier and the code cleaner. My concern is it uses "operator"s to do a lot of implicit conversions to make the code cleaner. If you are new to the library, looking at the code does not give you any clues as to why the compiler does not error out on apparent type match violations. After coding a lot with this pattern, I think it has turned out okay because all the library functions use these types to return value and pass/error state, kind of like your Result you had a video on.
@RobyMarcellino
@RobyMarcellino 7 ай бұрын
Cool way, but not explicit so might be confusing to some. Good video though, keep up the good work!
@UnseenScofield
@UnseenScofield 7 ай бұрын
Queue Enqueue them give it to WhenAll
@alexdobrynin
@alexdobrynin 7 ай бұрын
as for me, this is overengineering. how often in code do you need to await multiple independent tasks? not so often. Also, what if you need different generic types, what if you need different amount of tasks to await, each time you need to expand/add new functionality to your extension method. It's fun, it's weird, it's interesting, but it has no practical usage
@Hugo-pj4bm
@Hugo-pj4bm 7 ай бұрын
Yeah I agree. The usual way is only like 10 characters longer and more readable
@exmello
@exmello 7 ай бұрын
1. This is reusable. Stick it in a utility project somewhere 2. Even if you never use this yourself, you learned a C# feature and know what's going on if you see it used in a library somewhere. 3. I wasn't on board either until the last part of the video where he returns a tuple. I can see that as easier to work with is cases where you'd rather have named results and not have to iterate through an array. When you ask questions like this, always try thinking of answers first before becoming annoyed and saying it's useless. Most of the time in only takes a second two to construct some valid scenarios. Use that programmer brain of yours.
@PlerbyMcFlerb
@PlerbyMcFlerb 7 ай бұрын
​@exmello I'd think long and hard about using this exact approach. Imo this is a "great taste but awful execution" moment. Only one generic arg for example is silly.
@alexdobrynin
@alexdobrynin 7 ай бұрын
@@exmello when you give answers like this, always try thinking about how often will you use such things in your real projects and worth it to spend time to write such utilities and support them in future. It's all about spent time and profit gain
@shakeuk
@shakeuk 7 ай бұрын
Actually I have come across needing to await multiple independent things at the same time quite often, this approach is very useful.
@gregorymorse8423
@gregorymorse8423 7 ай бұрын
Interestingly enough only WaitForMultipleObjects on Windows and select on Linux are correct for doing a proper blocking parallel wait. Only the OS can manage CPU cores efficiently...
@angelochoameireles
@angelochoameireles 7 ай бұрын
Although its cool, and I really like it, I'm not a big fan of creating structures that later some programmer would see and would not understand what is going on
@KingOfBlades27
@KingOfBlades27 7 ай бұрын
Definitely not gonna use this. But still really interesting to see how you would write extensions like these. So overall thumbs up for the video 👍
@noahpeltier
@noahpeltier 7 ай бұрын
How I learned to do this is by adding Tasks to a Generic.List and then doing a WhenAll() on the collection. Is this any different than both methods described here?
@Wizatek
@Wizatek 7 ай бұрын
This already makes more sense to me. Sometimes i wonder why someone would create a async function, but then await it anyway. Maybe i am wrong but it would be the same as calling a normal function
@KingOfBlades27
@KingOfBlades27 7 ай бұрын
One important reason why you should use async functions even if you are waiting them is that you aren't blocking the current thread when you do that. This is important especially in desktop apps and similar applications that have a GUI. Also in many cases async methods tend to perform better.
@mt1104uk
@mt1104uk 7 ай бұрын
Hiding TaskEx contents behind a sign up is a bit naff.
@RealDieselMeister
@RealDieselMeister 7 ай бұрын
Use Task.WhenAll and decostruct the Aggreagte Exception in a try catch block.
@wojciechwilimowski985
@wojciechwilimowski985 7 ай бұрын
I'm going full stack, can anyone recommend a channel similar to Nick's but for frontend/JS stuff?
@Grimlock1979
@Grimlock1979 7 ай бұрын
Wow, I just posted this on Reddit 2 days ago :P
@Freakhealer
@Freakhealer 7 ай бұрын
Wouldnt it be better to use a params and allow any number of tasks?
@zabustifu
@zabustifu 7 ай бұрын
It is possible. The main downside is that you can't return a tuple if you do that. Also it becomes possible to call the method with no parameter (empty array), which can happen by mistake (seen it at work recently). Then again, the same goes for Task.WhenAll.
@stephenyork7318
@stephenyork7318 7 ай бұрын
I’d love to use this but it’s not viable for most of the times I’d need it. Would be nice if it could handle an arbitrary length of tasks as a list.
@PabloHarguindey
@PabloHarguindey 7 ай бұрын
I hate all the convoluted code to do something that seems very basic and understable just with the whenall. But I love to learn how to do it.!!! 🙂
@netanelpersik
@netanelpersik 7 ай бұрын
Cool Can't we use params Instead of N amount of tasks?
@oguzhan0Kahyaoglu
@oguzhan0Kahyaoglu 7 ай бұрын
Hey Nick, please shrink your face circle in your videos as it overlaps with the code you present :)
@user-lm9jm9ql1t
@user-lm9jm9ql1t 7 ай бұрын
I think it should be a built-in compiler feature
@The00Rex
@The00Rex 7 ай бұрын
Couldn't you somehow make a generic method by using params?
@Grimlock1979
@Grimlock1979 7 ай бұрын
If the tasks all have the same return type, sure. But you can already do that with Task.WhenAll. When the tasks have different return types, you want a Tuple.
@MrBenix181
@MrBenix181 7 ай бұрын
What about a list of tuple Tasks ?
@VitalMiguel
@VitalMiguel 7 ай бұрын
I've been using something similar: public static async Task AwaitAllAsync( Task task1, Task task2) { _ = task1 ?? throw new ArgumentNullException(nameof(task1)); _ = task2 ?? throw new ArgumentNullException(nameof(task2)); var t1 = await task1; var t2 = await task2; return (t1, t2); } And then: var (products, weather) = await TaskExt.AwaitAllAsync(productsRepo.GetAllAsync(), weatherService.GetAsync()); This will desconstruct the tuple into two different variables with two different outputs. If you need more parallel tasks you can create more overloads.
@MoskowGoAwayFromUa
@MoskowGoAwayFromUa 6 ай бұрын
IMO this affects maintainability of the project. It will be much more complicated to understand what's going on inside when someone else will review that code in a year.
@jewersp
@jewersp 7 ай бұрын
Interesting approach. In the end, it's mostly syntactic sugar, because you're still using Task.WhenAll() (or the TaskExt.WhenAll() variant).
@Bliss467
@Bliss467 7 ай бұрын
Really wish we had array literals with square brackets and destructuring arrays in the language so that we needn’t extend every size of tuple and arrays are easier to work with than tuples
@efrenb5
@efrenb5 7 ай бұрын
Feels like a lot of code for some syntactic sugar that doesn't really improve readability that much. I see myself explaining over and over to other devs why I'm doing all that when I could just call Task.WhenAll directly and avoid adding a method to the call stack.
@radol
@radol 7 ай бұрын
Hacking language syntax to solve non-issues like this is never a good idea, it reminds me of overusing macros in C++. Can IDE even navigate to such extension method definition?
@Astral100
@Astral100 7 ай бұрын
That is until you need to process possible errors from the tasks
@nickchapsas
@nickchapsas 7 ай бұрын
That's what the TaskExt.WhenAll method solves :)
@furkanyldz1658
@furkanyldz1658 7 ай бұрын
And what is TaskExt.WhenAll ?
@RealDieselMeister
@RealDieselMeister 7 ай бұрын
@@furkanyldz1658possible a try catch, which extract the inner exceptions in the aggregate exception. ;)
@galberts
@galberts 7 ай бұрын
I don't like it really, because syntax gets cluttered with more tasks, and most of the time you want to do something with the result so you want the tasks in a Task variable anyway.
@luc9volts
@luc9volts 7 ай бұрын
Why ?? 😅
@royvethanayagam5888
@royvethanayagam5888 7 ай бұрын
Why not? 😂
@Light_Akira
@Light_Akira 7 ай бұрын
because he can. the most common reason for any over engineered and obfuscated solution.
@neighbourhater
@neighbourhater 7 ай бұрын
Cool idea, but in the end it's overcomplicated and under the hood you don't gain anything, it doesn't even really shorten the code using the extension than to use whenall directly...
@5cover
@5cover 7 ай бұрын
Using Task.WhenAll has the benefit of leaving no room to interpretation. Whereas the tuple approach makes it unclear about what's going on, especially for soemone who didn't write the code. Does it wait for all the tasks to finish? Or for any of them? Plus the extension method is called implicitly, thus the code is hidden from view. You cant "jump to definition" to see what it does. That makes it implicit and obfuscated. The cost of having 11 more characters is negligible. I guess this could be useful in rare scenarios when Task.WhenAll is used very frequently, but even then I don't think it's worth it. Overall, this is a bad approach. Please don't write code like this.
@petropzqi
@petropzqi 7 ай бұрын
This is codesmell to be. You have just generated a syntax, that no-one understand. Why not use awaitAll as we all can relate to and can read about at the official documentation?
@failgun
@failgun 7 ай бұрын
The fact that you would need to individually define umpteen generic overloads for different numbers of tuple parameters utterly ruins this from ever being useful for me in a real project. C# so badly needs variadic generics, you could write code like this all day and it would be wonderful, but it seems like we'll never get them.
@aprobinda
@aprobinda 7 ай бұрын
This example does not look "cool" to me. Instead of just using the familiar Task.WhenAll, it adds complexity. I would not want to see it in production code.
@istovall2624
@istovall2624 7 ай бұрын
looks like a leaky abstraction to me
@metaltyphoon
@metaltyphoon 7 ай бұрын
Please don't do this in your codebase. It's just being clever to the sake of being clever. Write code in a way that someone, could even be yourself, can read in the future without surprises.
@RealDieselMeister
@RealDieselMeister 7 ай бұрын
haleluja or shakka or what ever. Word! Please follow this advice!
@kondozarez3476
@kondozarez3476 7 ай бұрын
I don't know why would anyone check London weather? 🤷‍♂
@ryan-heath
@ryan-heath 7 ай бұрын
Noice! 😎
@royvethanayagam5888
@royvethanayagam5888 7 ай бұрын
What noise?😀
@Zashxq
@Zashxq 7 ай бұрын
not a fan of the hidden implementation details tbh; i'd rather make it explicit with some kind of fluent api personally
@juliendebache8330
@juliendebache8330 7 ай бұрын
This is so inefficient. What you should do instead is create a static class and store the weather for London as a member there...
@CarrigansGuitarClub
@CarrigansGuitarClub 7 ай бұрын
Emmmm, not sure their is a real benefit here, your cleaning up the code to your "company's coding standards"...but that standard approach isn't common!
@qwerty01453
@qwerty01453 7 ай бұрын
Eww no
@DryBones111
@DryBones111 7 ай бұрын
A lot of work for a little bit of sugar. I'm not sure I hate "Task.WhenAll" so much that it's worth doing this.
@amolaher7630
@amolaher7630 7 ай бұрын
Hey Nick, great way to implement multiple task concurrently , task.whenAll could do the magic concurrently however you are keep saying parallels , just want confirm if anything changes in recent c# version for Async execution .
@ralphmaasgmailcom
@ralphmaasgmailcom 7 ай бұрын
Cool
The New .NET 9 HybridCache That You Must Upgrade To!
14:34
Nick Chapsas
Рет қаралды 43 М.
Every New Feature Added in C# 12
14:19
Nick Chapsas
Рет қаралды 147 М.
Каха инструкция по шашлыку
01:00
К-Media
Рет қаралды 8 МЛН
$10,000 Every Day You Survive In The Wilderness
26:44
MrBeast
Рет қаралды 130 МЛН
Increíble final 😱
00:37
Juan De Dios Pantoja 2
Рет қаралды 48 МЛН
Stop using async void in C#! Do this instead.
13:12
Nick Chapsas
Рет қаралды 57 М.
Make Your LINQ Up to 10x Faster!
11:08
Nick Chapsas
Рет қаралды 53 М.
Why I Quit the Scrum Alliance
7:58
The Passionate Programmer
Рет қаралды 7 М.
C# Async Await Mistakes | Part 1
10:19
Amichai Mantinband
Рет қаралды 30 М.
That's NOT How Async And Await Works in .NET!
12:25
Codewrinkles
Рет қаралды 15 М.
Why Startups Hate .NET and C#
10:38
Nick Chapsas
Рет қаралды 244 М.
you need to stop using print debugging (do THIS instead)
7:07
Low Level Learning
Рет қаралды 407 М.
8 await async mistakes that you SHOULD avoid in .NET
21:13
Nick Chapsas
Рет қаралды 308 М.
"Stop Using Async Await in .NET to Save Threads" | Code Cop #018
14:05