Тёмный

Correcting Common Async/Await Mistakes in .NET - Brandon Minnick 

NDC Conferences
Подписаться 193 тыс.
Просмотров 166 тыс.
50% 1

Did you know that the .NET compiler turns our async methods into classes? And that .NET adds a try/catch block to each of these classes, potentially hiding thrown exceptions? It's true!
In this session, we will learn how to best use async/await in C# by analyzing how .NET compiles our async code.
Join me as we take an existing app and optimize its async code together, showing off performance gains, better exception handling, improved run-time speed, and smaller app size!
Check out more of our talks in the following links!
NDC Conferences
ndcoslo.com
ndcconferences.com

Наука

Опубликовано:

 

9 июл 2019

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 120   
@Miiite
@Miiite 5 лет назад
This is a terrific presentation. Detailed, technical, yet exposes simple examples. Just love it, thanks
@NickBullCSharp
@NickBullCSharp 3 года назад
This has definitely been eye opening. There's a lot of great information here. This'll most definitely help with a lot of the code I am currently writing. Thanks for uploading :)
@ocallesp
@ocallesp 4 года назад
For new C# sharp developers this video is good ! thanks
@Moosa_Says
@Moosa_Says 9 месяцев назад
Honestly best talk ever !! thanks a lot.
4 года назад
I've learned something today so great talk.
@MobilTemp
@MobilTemp 4 года назад
Amazing video, great tips.
@andreyka26_se
@andreyka26_se 5 лет назад
Come on, people, You all need to read Richter. Async is not about multithreading at all. Async is about forcing your thread to do something when your network card's driver do all job, or when your disk's driver do all job. it is not important what thread will continue execution(like the speaker said on the first sample)./ Event thread1 can continue execution if it gets from the thread pool. It doesn't matter at all.
@nikhilrathore2385
@nikhilrathore2385 2 года назад
But isn't multi threading also the same. Multiple threads running on single CPU core. The core keeps switching between multiple tasks (threads) either because a thread is making a network call or some I/o operation. The way I look at it, async await looks similar. You just continue executing the non dependent code without waiting for the response (Context switching). Could you please elaborate
@andreyka26_se
@andreyka26_se 2 года назад
@@nikhilrathore2385 no, it is not the same. Async is about moving job to other device from CPU, or more precisely: making CPU not to wait until something is being done by other device.
@nikhilrathore2385
@nikhilrathore2385 2 года назад
@@andreyka26_se by other device do you mean other CPU core? If yes, then how is it possible since we have limited cores(4 or 8 mostly) and we run multiple apps together with the apps themselves doing lot of things (like browser handling multiple tabs).
@andreyka26_se
@andreyka26_se 2 года назад
@@nikhilrathore2385 no, I mean, I/O devices: drive, network card, etc. CPU cannot read the file, as I know, the specific driver does it. The same is for network card, and other I/O stuff.
@nikhilrathore2385
@nikhilrathore2385 2 года назад
@@andreyka26_se yes that makes perfect sense. But now in multi threading also the same thing happens. single core switches between 2 or more tasks. So if we consider 1 CPU core, both multithreading and async says that a single physical worker(CPU core) will switch between those task whenever 1 task doesn't need CPU for some time, like when it needs to do some io or network call. Is the difference just that in async, we just tell that which code needs to wait for the blocker to be resolved and which code is independent (through callbacks in terms of javascript). while in multithreading we are in complete charge of making the tasks and allocating them to threads and we are ones who decide when will context switch happens. Becuase end of the day we have 1 core, 1 single worker that is managing multiple task by switching between them and also at any point of time, it can just do atmost 1 operation. So the difference is still not clear to me
@user-xd1su3sk3i
@user-xd1su3sk3i 3 года назад
Very clear and useful. Thanks.
@caractacustube
@caractacustube 4 года назад
At 0:06:00 you say that the await keyword spawns a new thread from the thread pool? This is incorrect. Only an awaited IO-bound takes will return the thread, and invoke the continuation on an IO completion thread.
@IvarDaigon
@IvarDaigon 3 года назад
One thing completely missing from this video is that you should make a habit of not passing Lists or Dictionaries into Async code because they aren't thread safe and you have no real way of knowing ahead of time which thread may be accessing or modifying them. Even if you don't intend on modifying them in your code, some developer in the future may do so and it will cause all sorts of problems. It is far safer to just get into the habit of using any of the System.Colllections.Concurrent types (CuncurrentDictionary etc) by default. I would also argue that handling errors and logging them within your functions themselves and using the Try pattern (like TryAdd TreyRemove etc where you return success or failure rather than throwing exceptions) is far safer and easier to debug and maintain than using extension functions that allow people to call Async void function whenever they like and then catch any errors. The later assumes that the developer calling the function is aware of all of the different types of exceptions that can be thrown which is almost never the case and you lose access to the stack frame variables so putting a break point in your catch block outside of the function call will yield almost no helpful information. Async void should really only be used for event handlers that you have no control over such those auto generated when you double click in UI elements in visual studio. It is for backwards compatibility only and should be treated that way. Final note: Setting ConfigureAwait(true) as the default option was a poor design choice on the part of Microsoft. If code is not directly touching UI elements then it usually does not need to return to the same context from whence it game. This is true for about 99% of the await calls in a typical application so developers have to put ConfigureAwait(false) all over their code which is not only very tedious but also makes the code look very ugly.
@MayankGupta303
@MayankGupta303 3 года назад
One word. Amazing
@roodborstkalf9664
@roodborstkalf9664 5 лет назад
Excellent
@Tyrrrz
@Tyrrrz 5 лет назад
Thinking about async in terms of thread pool is conceptually misleading
@sgerar37
@sgerar37 4 года назад
I agree 100% with your thought; unfortunately, the async-await machinery is one of the leakiest abstractions I have ever used in programming and IMHO the current implementation (relying on a state machine that is typically executed by the thread pool) shouldn't exist in an OS that offers recursive locking constructs like Windows. We recently experienced a deadlock nightmare by some sync code I migrated to async. The original code was calling some third-party code, that was labeled thread-safe, but unfortunately (as we had to find out using Windbg) it was synchronized using recursive locking. The third-party code assumed that a sequence of lock-step related operations would always be executed by the same thread. Our unit-test code completely missed this problem, since the async calls were not awaited with ConfigureAwait(false) and the test ran inside a synchronization-context (forcing the continuations to be run on the same thread and hiding the problem). So my point is you REALLY REALLY need to be aware of the implementation details in order to avoid shooting your leg, or if you have done (as in my case) be able to understand why you blew it off.
@darkopz
@darkopz 8 месяцев назад
Misleading maybe. Important to realize, absolutely. It’s possible to write long running tasks with async/await that eat the entire ThreadPool. And it’s not obvious.
@mieszko5260
@mieszko5260 2 года назад
Did I understand correctly - it is better practive to always declare interfaces with ValueTask instead of Task ?
@ferzik1508
@ferzik1508 4 года назад
@58:58 Task.Run() will put code on different threadpool thread ...
@gabeanthony8910
@gabeanthony8910 4 месяца назад
Yes. It is scheduled on a threadpool. It might run on the same thread, or it might not. But the statement the presenter makes "dotnet isn’t going to put that task on a thread..because we didn't use the await keyword" is wrong, I feel. It confuses an already confusing topic.
@jasonracey9600
@jasonracey9600 2 года назад
This is the first time I feel like I understand the purpose of ConfigureAwait(false), thanks.
@marounbassam
@marounbassam 2 года назад
In the slide where you showed the usage of "ConfigureAwait", isn't it enough to use it only for the first call? It'll be returned to a different thread, and I don't care if that different thread is awaiting again, it's already not the UI thread that I didn't want it to await.
@AyuNeko
@AyuNeko Год назад
i was thinking the same thing. I think it is enough to use it only for the first call to free up the UI thread. But if you don't use it later down the line, it always waits until that one caller thread is available instead of using just any thread which is available, which would be more performant i think. not sure though....
@serhiihorun6298
@serhiihorun6298 4 года назад
Thanks
@drullo
@drullo 3 года назад
Good information. And Brandon sounds exactly like John Krasinski from The Office.
@brandonminnick
@brandonminnick Год назад
😎
@khanabadosh_shekhar
@khanabadosh_shekhar 4 года назад
54:30 I was wondering the same
@jamesnorbury8661
@jamesnorbury8661 5 лет назад
Great talk with some good advice! However, I don't like the fire and forget call to an async void method in a constructor 31:41. The case made is that because the code inside the async void method uses await, any exception which is thrown will surface correctly, so it is fine to do. While it is true that exception handling is correct; there is a possibility that a slow network connection will mean this newly constructed class is used before it is ready. E.g. a list initialized to the result of an API call, a NullReferenceException would be thrown if trying to access an item from this list before the async method completed. It seems more reasonable to await calls to the API before creating the view model, then pass the results into the view model's constructor so it is instantiated correctly. This method doesn't lock the UI thread and seems safer to me than calling a fire and forget in a constructor. While I don't doubt that in the current situation this fire and forget won't cause any issues, I wouldn't say it was a best practice but more of an interesting edge case. I could see this being useful for truly fire and forget tasks like adding something to a queue.
@user-il5fc2qk6t
@user-il5fc2qk6t 5 лет назад
James Norbury Yeah, that's a great point!
@SpaceShot
@SpaceShot 5 лет назад
I have also been thinking about a scenario like a "web server startup" where it was common practice to do things in global.asax methods. Those methods existed before async/await so people often block while making sure dependencies are in place. I think you could also create a Task with that initialization and then await it where it is needed (since the task is complete, await is almost a no-op). However, using modern frameworks in ASP.NET Core, this concern goes away.
@TheAceInfinity
@TheAceInfinity 8 месяцев назад
13:17 I wouldn't say it's "gone forever".. It's just placed on the Task object. Continuation tasks also have a nuance in that it's a different task so awaiting the continuation task means that the original task's exception does not propagate to be thrown.
@joephillips6634
@joephillips6634 5 лет назад
at 33:23 you should probably just call the refresh method after constructing the class IMO
@dogpixels
@dogpixels 4 года назад
I hit the same question just yesterday (wanting an app to load some stuff upon start), and my answer was simply to hook up the ExecuteRefreshCommand() to the MainWindow's OnLoaded event. Wish the presenter would have mentioned that simple solution to a common question.
@KoScosss
@KoScosss 3 года назад
Or use async static factory method
@volan4ik.
@volan4ik. 5 лет назад
I'm surprised that nobody asked about ContinueWith method which can easily replace the FireAndForget call. It brings the support for exception handling of non-awaited calls, for continuation of parent task so we can easily handle result if task succeeded. Also nobody remembered about Task.Factory.ContinueWhenAll and Task.Factory.ContinueWhenAny methods
@SpaceShot
@SpaceShot 5 лет назад
I'm not sure how I feel about the FireAndForget advice at all. In ASP.NET Core just about everything has an async interface or implementation where you wouldn't need this. In .NET Framework the lagacy frameworks predated async/await so there are scenarios where you are in a sync method and want to fire off something async. I think I like a technique where that is fired off as a Task that can be awaited by interested code that wants to know that Task was completed or not.
4 года назад
Well the talk is about async/await and I guess he wanted to focus on that and not on the entire Task system which is much richer.
@figloalds
@figloalds 4 года назад
Forgot to say that uncaught Task exceptions bricks the program when the Task is garbage collected; And also that .Wait() and .Result will may cause crazy deadlocks
@baz5719
@baz5719 5 лет назад
Great speaker.
@duke227
@duke227 4 года назад
What tool did you use to display the compiler generated code?
@keja0
@keja0 4 года назад
I use the ILSpy addon for VisualStudio/Code
@aresagathos2075
@aresagathos2075 4 года назад
I did this example with HttpClient, with dependency injection calling the async function from a constructor, and i was unable to catch the exception, despite i was awaiting the example. Still don't know why the state machine doesn't rethrow the exception to date.
@symix.
@symix. Год назад
I know its been 2 years but... how did you await inside constructor? it isnt possible..? And if it was not awaited, then it doesnt matter if you awaited inside it.
@aresagathos2075
@aresagathos2075 Год назад
@@symix. Task.Run. And meanwhile i know that c# can't catch exceptions in this specific cases.
@Seedzification
@Seedzification 5 лет назад
If you need to put configureAwait on every "await" keywords, that's a design flaw imo.
@SpaceShot
@SpaceShot 5 лет назад
You only use it if you don't care about returning to the original context. In app development, you usually do... because you want to get back to the GUI thread on desktop or to a thread with the http request context restored on web servers. If you are writing libraries, including libraries for your own consumption, then you usually DON'T need to return to the same context. There was some talk about adding features where you might "configure" for a whole project or class or namespace, but you figure the general consumption case here is the app developer. The library developer does need to learn a bit more, yes.
@PanzerFaustFurious
@PanzerFaustFurious 5 лет назад
at 44:50 , should we use ValueTask if we might not hit await, or should we use ValueTask if we expect to not hit await often? Because, lets say we have an API that returns badrequest when the modelstate is invalid. This doesnt happen often, but still, the api might not hit await. Should we still use ValueTask?
@Miggleness
@Miggleness 5 лет назад
Best example is with in-memory caching. When your async method is more likely to return a result that is already in memory rather than do an async operation (I/O), then using ValueTask is more appropriate since you dont allocate a Task on the heap. In the event that fetch data from your asynchronously, ValueTask will create a Task since we now need to store the state on the heap.
@Miggleness
@Miggleness 5 лет назад
For your use case, use Task still. I imagine that the aspnet core middleware could call await on your async API method more than once. Whereas, you can await on a ValueTask just once
@miamiviceclips
@miamiviceclips 5 лет назад
This conf is interesting (avoid async void, use configureawait ok) but i'm not sure why and when use AsyncCommand?
@volan4ik.
@volan4ik. 5 лет назад
While using MVVM pattern (usually in WPF applications)
@volan4ik.
@volan4ik. 5 лет назад
Why - because usual ICommand, which is a part of pattern, is only synchronous. And we may need to have a mechanism of running async code as well (together with bindings etc).
@samueldebeer2306
@samueldebeer2306 2 года назад
This is incorrect. A new thread is not created to simply await the task. The thread executing the method reaches the I/O bound method that is awaited and is then freed up to do other things until the task is completed, since there is nothing the CPU can do except wait for this task to be completed by an external 'computer' somewhere else. The idea that another thread is brought in to wait for the task to complete, thus blocking itself from doing anything, would be a bit pointless, as you'd still be wasting resources. If I'm not mistaken, the presenter is describing a scenario that is closer to calling Task.Run(), which would use another thread to run whatever code you'd like, which in this case wouldn't make sense, as the DownloadDataTaskAsync method being executed is I/O bound and the thread you've created to await the I/O bound task, like I said, would just sit and do nothing.
@chadiusmaximus9350
@chadiusmaximus9350 2 года назад
not a bad talk but I'd like to point out that the compiler only generates a class in debug mode. in release it generates a struct. i.e it performs better because it's running on the stack.
@sach2372
@sach2372 4 года назад
Resource link - codetraveler.io/ndcoslo-asyncawait/
@sumitsharma5537
@sumitsharma5537 4 года назад
Fantastically Insane .
@konstantinsarychev9305
@konstantinsarychev9305 5 лет назад
Ridiculous optimization with ValueTask taking into account that new class is created each time we use await. If I got it correctly.
@volan4ik.
@volan4ik. 5 лет назад
Class is created for every method marked with async keyword, not for every await keyword. 'await innerTask' is compiled into assignment of inner.GetAwaiter() and into changing the state. ValueTask does make sence when we return from async method before any 'await' is called, so less allocations are needed.
@mattiasmartens9972
@mattiasmartens9972 2 года назад
does safeFireAndForget() offer any advantage if there is no handler supplied to onError?
@BBTRaziel
@BBTRaziel 11 месяцев назад
From what I understood from the video, the only purpose in that case would be to avoid future mistakes while maintaining the code. Because it would make it very clear that you are "setting free" the Task on purpose. From a practical and technical point, there is no difference in the execution of the code
@JustinRomaine
@JustinRomaine 4 года назад
If you are not using the await keyword and just returning a Task then whats the point in making the method a task at all. Seems there is no point in async when you are not waiting form multiple tasks to complete simultaneously within a method
@igorsentrxigorsentrx5550
@igorsentrxigorsentrx5550 3 года назад
How presenter at conference could make so many mistakes ?! How video with all pointed mistakes could receive such a high like\dislike rate ?!
@F2H16
@F2H16 5 лет назад
Unless I'm missing anything , "The Result property is a blocking property. If you try to access it before its task is finished, the thread that's currently active is blocked until the task completes and the value is available. In most cases, you should access the value by using Await or await instead of accessing the property directly" says docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2013/hh524395(v=vs.120) So, var result = await task1 and var result = task1.Result are not identical.
@GeorgeTsiros
@GeorgeTsiros 2 года назад
what does sharplab show you?
@gregorymorse8423
@gregorymorse8423 4 года назад
So what if you need to do 100 asynchronous operations and finally return to the calling thread at the end. Obviously the first ConfigureAwait false has lost context. So it seems you use 100 ConfigureAwait false in a task and call that task with ConfigureAwait true in the one place returning to the calling thread. This way far less synchronization takes place than using ConfigureAwait true 100 times.
@Tydides64
@Tydides64 4 года назад
How does a developer advocate at Microsoft think that awaited methods run at new thread? They don't. Read some Stephen Cleary please, this is embarrassing.
@Stashix
@Stashix Год назад
Does Developer Advocate mean he'll represent me when I go to trial for all my coding transgressions?
@brandonminnick
@brandonminnick Год назад
I handle these on a case-by-case basis
@joephillips6634
@joephillips6634 5 лет назад
at 22:05, does it really jump back to the original thread or does it just store the context and copy that over to a thread but not necessarily the original one?
@alexandertkacuk8712
@alexandertkacuk8712 5 лет назад
I would like to know it too. And i have not found the location in the source code yet.
@TellaTrix
@TellaTrix 10 месяцев назад
Wow! Finally, got to know how bad developer am I?
@buddysnackit1758
@buddysnackit1758 2 года назад
Let's Go Brandon!
@mohamedauf3668
@mohamedauf3668 4 года назад
One should highlight, that he's talking about .NET only. Mechanisms are different in (asp).net core, e.g. there's no SynchronizationContext in asp.net core. blog.stephencleary.com/2017/03/aspnetcore-synchronization-context.html
@marcelg861
@marcelg861 5 лет назад
.ConfigureAwait(false) 🤯
@philipmrch8326
@philipmrch8326 5 лет назад
I rarely use it, as sometimes I have events that will be invoked after an await, and I want it to run on the original context (if there is a SynchronizationContext/TaskScheduler)
@volan4ik.
@volan4ik. 5 лет назад
@@philipmrch8326 TaskScheduler is not the same as SynchronizationContext. Follow the link to get a great explanation: stackoverflow.com/a/55085418
@dotnetdevni
@dotnetdevni 3 года назад
How do i fix this its a nightmare A database operation failed while processing the request. InvalidOperationException: A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see go.microsoft.com/fwlink/?linkid=2097913.
@owickedfox
@owickedfox 2 года назад
For me, it would be 100/100 if he used CancellationToken in every async function.
@TheLaucomm
@TheLaucomm 4 года назад
Though there continue to be correct practical advice in his talk, he still hasn't understood how async await actually works. He still incorrectly assumes that there is a connection between await and spawning another thread and other details that are just wrong. Async await isn't about multi threading, its about I/O bound operations. The whole idea is about avoiding the use of multiple threads. Only just by it's nature, async await CAN also be used in multi threaded scenarios, but that's not the main case, just a benny. This is explained in a really simple way, that anybody can understand in this youtube video: ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-hB0K1JWFoqs.html
@mounirbenhalla4191
@mounirbenhalla4191 4 года назад
thanks for video,, its the true story for await and async
@razibtx
@razibtx 2 года назад
Thank you..thank you thank you..I was looking for this for last several days. thank you.
@brandonminnick
@brandonminnick Год назад
> he still hasn't understood how async await actually works I do. Promise. Async/Await is an incredibly complex topic and this presentation is limited to 60 minutes. I had to purposefully omit delving into certain topics. The discussion on thread spawning could be a 60-minute talk on its own.
@VareneVino
@VareneVino Год назад
Do NOT use ConfigureAwait(false). The default is there for a reason and that reason is Context!
@framepointer
@framepointer 2 года назад
.ConfigureAwait(false) is really poor design.
@csexton07
@csexton07 Год назад
C# its Id not ID and make async methods with the Async suffix so that way I can read it, oh this is an async method.
@belowasmelashgebremariam
@belowasmelashgebremariam 2 года назад
Kemey ke
@rentefald
@rentefald 5 лет назад
First signs of code that will later work in harmony of AI, that eventually will lead to the Terminator.
@garryiglesias4074
@garryiglesias4074 4 года назад
Are you lost and this is your first programming encounter ?
@ZdenoTirc
@ZdenoTirc 4 года назад
Ah, many misconceptions. Looks like speaker doesnt understand async await very well.
@radicalbyte
@radicalbyte 3 года назад
Sorry, I can't get over the American YO BRO college guy voice, it triggers my "recruiter bulls***" filter.
@washedtoohot
@washedtoohot 2 года назад
Lol. The guy is still legit though
@samueldebeer2306
@samueldebeer2306 2 года назад
@@washedtoohot He fundamentally misunderstands async await when he says a new thread is created to await the I/O bound task.
@brandonminnick
@brandonminnick Год назад
I'll try to be born with a different voice next time
@Micke2nd
@Micke2nd 2 года назад
When we already speak about wrong using, why waste time of the audience with an introduction into basics like multithreading, etc. ?
@belowasmelashgebremariam
@belowasmelashgebremariam 2 года назад
AnneAsmelash
@maksymkazakov221
@maksymkazakov221 5 лет назад
An interesting conf, but drinking sound is really annoying.
@tehklevster
@tehklevster 2 года назад
This is fine if developing a desktop UI app. You didn't cover the benefits or otherwise when building web apps, for which I can see no advantage. Yet I see this all the time in our codebase because cargo cult. Also some MS API's force you to use async (some of the Identity packages), and it generally annoys me in a web app where we're doing nothing clever.
@ankhayratv
@ankhayratv 5 лет назад
To any speaker: do not drink unless you really need to!
@belowasmelashgebremariam
@belowasmelashgebremariam 2 года назад
Ewe Anne Asmelash Eye
@MadaFakaTOO
@MadaFakaTOO 3 года назад
So they're letting absolutely anyone do a talk now, huh?
@jacksonstevemartinez9468
@jacksonstevemartinez9468 3 года назад
Kose Nanat
@belowasmelashgebremariam
@belowasmelashgebremariam 2 года назад
EweNattey
@shenth27
@shenth27 3 года назад
Microsoft guy using Apple computer..
@belowasmelashgebremariam
@belowasmelashgebremariam 2 года назад
EweAsmelash
@belmiris1371
@belmiris1371 5 лет назад
Wow. So much excitement about making code less and less readable and maintainable. "Here's a new magic thing-a-majig that does a thing you already have 10 other (clearer) ways of doing but it's NEW!" Depressing.
Далее
Writing Allocation Free Code in C# - Matt Ellis
1:00:15
From WCF to gRPC - Mark Rendle
1:04:33
Просмотров 43 тыс.
How to Do 90% of What Plugins Do (With Just Vim)
1:14:03
Просмотров 871 тыс.
8 await async mistakes that you SHOULD avoid in .NET
21:13
Patterns for high-performance C# - Federico Andres Lois
1:08:55
Игровой Комп с Авито за 4500р
1:00