C# Async Await Mistakes | Part 1

preview_player
Показать описание
Connect with me on 'em socials:

#dotnet #csharp
Рекомендации по теме
Комментарии
Автор

Thank u for starting explaining the most "unexplained" charters of the await/async in a very concise way. Waiting for the next parts. It will be great that u show how to handle correctly the concurrency use cases (when we try try to update the same "list/array/etc" from different tasks.

alexlo
Автор

It seems messy, but the motivation for MS building it this way is clear. If everything was going smoothly until the cancellation token was triggered, then what you want is a "one cancellation exception to rule them all" and that's what is thrown. If *any* of those tasks threw a "genuine" exception, you absolutely do not want that to be overlooked by virtue of you having caught an OperationCanceled exception. This is why having two separate catch blocks (one for when the CTS was triggered, the other for real errors) is a good pattern.

You could argue that the real WTF here is that triggering a CTS results in an exception being thrown, but given that the cancellation could be initiated by an external source (OS shutdown in progress, for example) and that pushing an exception onto a thread is the quickest way to stop it, I can see why it was engineered this way.

alexclark
Автор

I'm curious when is it safe to access task.Result?
And how do we work with Task.WhenAlll if all of the tasks return a result of different type?

Just some cases which I found interesting while learning about Task.WhenAll, that I think your viewers may find interesting.

MilanJovanovicTech
Автор

This is a perfect example why using a framework for more complex designs/scenarios is never as big a time saver as one might think.

emyrulz
Автор

So the AggregateException thrown is absolutely useless because the actual "source of truth" lies in each of the original tasks. AggregateException does not contain all of the exceptions, just some of them depending on some still unclear criteria. While this is fantastic short video to explain some of this really confusing behavior deeply embedded within the async/await implementation, it does beg the question "why is it done this way?". This is a complaint about the implementation itself and not meant to detract from this video which does a great job of explaining the high level overview of this problematic behavior. Either the AggregateException class should contain an aggregate list of ALL exceptions or it should be renamed to because this is really just another way to make our already difficult jobs much harder for no apparent gain.

willdavis
Автор

I was not aware of it. Great video. Thanks!

martinpolansky
Автор

Learning something new every day👍🏽
Thanks for sharing the knowledge🙏🏼

ArnonDanon
Автор

Hi Amichai, can you please make a video on how you set your visual code and which extensions you used in it.

muhammadqasim
Автор

I was not aware of it, but im actually doing it correct xD.
I have a for each loop on my users and i have a method which needs much processing so i add them as a task for each of the user so they can process in parallel, and then i await the list<tasks>.

My question to you is, if you know how can i start all the task at the same second?

var tasks = new List<Task>();
foreach (var user in Users)
{
tasks.Add(Process(user, Filter.Intense));
tasks.Add(Process(user, Filter.Medium));
}

await Task.WhenAll(tasks);

the moment i Add them they start instantly, is there a way to add them and only after start in parallel?

kaidouz
Автор

Hi Amichai,

Thanks for the video. Could you please share the name of the tool that you use to draw the arrows on the screen?

Thank you so much

paulostradioti
Автор

That's some interesting behavior I didn't know about. But I arrive at a different solution.
If you do a first, it'll hit only when everything has been cancelled, without any additional errors.
Followed by a Catch(Exception) block where one can handle the cases where a "real error" occurred and the whenAllTasks.Excepion will not be empty. In this scenario, I don't feel I need the OperationCancelledExceptions.
Making two Catch-Blocks like that, I don't see a need for the the list of *all* Exceptions.

Azcane
Автор

What a mess!!!! This stinks and should be redesigned in the framework! Thanks for the explanation :)

paviad
Автор

Never had problem with it. It seems intuitive for me.

mabakay
Автор

Hi! I like your videos, esp. the clean/DD series but, do you have any plans about when to show up on mastodon (or at least crosspost)?

reinhardlackner
Автор

So I should manually catch exceptions around every task.whenAll or is there an option to write it once in middleware?

adrian_franczak
Автор

Im surprised that the syntax and the way C# (or dotnet) handle exceptions in async tasks are similar with Python.
I wonder if there is anything similar to the Pythons exception group. and how can C# handle exceptions within multiple tasks where you should keep the other "no exception" tasks running?
e.g) WhenAll(goodTask1, errTask1, goodTask2) and I want goodTask1 to keep running whether errTask1 raise exceptions

ssh
Автор

This is a very good example of why you should consider making all of your functions Try functions where the exception is handled inside the function itself and any details are logged because when you throw exceptions out of each function it gets very messy very quickly and there is no guarantee that the exception will be handled properly by the caller.

Also if you really must know the reason why the function failed at the time of calling, you can always return a tuple containing a bool indicating whether the function succeeded or failed and the exception itself or a text description of what went wrong.

IvarDaigon
Автор

Unrelated question: What software is used to draw on screen?
Good work on explaining Task. WhenAll! Keep up the good work!

Rob_III
Автор

Bad description of the problem.
Task.WhenAll is a method that returns TASK, so use await same as for any task.

pierre
Автор

Uhm when i have done this i put the try catch inside the method that is being called, which is inside a service with its own logger.
Is that bad? Im not doing libraries for others to use at the end im the only one using that code. But if it's a method that i call many times, instead of always writing the try catch outside i just do it inside.
(This before i ve found about oneof and your amazin errorOr)

But hey i'm a dumb junior dev what do i know xD

ghevisartor